Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  [WATCHDOG] pcwd_usb.c generic HID include file
  [WATCHDOG] watchdog miscdevice patch
  [WATCHDOG] rm9k_wdt: fix interrupt handler arguments
  [WATCHDOG] rm9k_wdt: fix compilation
diff --git a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
index 29b3f9f..ce0666e 100644
--- a/Documentation/cpu-freq/core.txt
+++ b/Documentation/cpu-freq/core.txt
@@ -24,7 +24,7 @@
 1. General Information
 =======================
 
-The CPUFreq core code is located in linux/kernel/cpufreq.c. This
+The CPUFreq core code is located in drivers/cpufreq/cpufreq.c. This
 cpufreq code offers a standardized interface for the CPUFreq
 architecture drivers (those pieces of code that do actual
 frequency transitions), as well as to "notifiers". These are device
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 46f2a55..64ce44d 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -216,17 +216,6 @@
 
 ---------------------------
 
-What:	i2c-ite and i2c-algo-ite drivers
-When:	September 2006
-Why:	These drivers never compiled since they were added to the kernel
-	tree 5 years ago. This feature removal can be reevaluated if
-	someone shows interest in the drivers, fixes them and takes over
-	maintenance.
-	http://marc.theaimsgroup.com/?l=linux-mips&m=115040510817448
-Who:	Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
 What:	Bridge netfilter deferred IPv4/IPv6 output hook calling
 When:	January 2007
 Why:	The deferred output hooks are a layering violation causing unusual
@@ -270,3 +259,25 @@
 Who:	Patrick McHardy <kaber@trash.net>
 
 ---------------------------
+
+What:	ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
+When:	December 2006
+Why:	Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
+	functionally very much similar. They talk to ACPI in same way. Only
+	difference between them is the way they do frequency transitions.
+	One uses MSRs and the other one uses IO ports. Functionaliy of
+	speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq.
+	That means one common driver will support all Intel Enhanced Speedstep
+	capable CPUs. That means less confusion over name of
+	speedstep-centrino driver (with that driver supposed to be used on
+	non-centrino platforms). That means less duplication of code and
+	less maintenance effort and no possibility of these two drivers
+	going out of sync.
+	Current users of speedstep_centrino with ACPI hooks are requested to
+	switch over to acpi-cpufreq driver. speedstep-centrino will continue
+	to work using older non-ACPI static table based scheme even after this
+	date.
+
+Who:	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+---------------------------
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index af6defd..8ccf0c1 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -54,3 +54,6 @@
 intr		(*)	Allow signals to interrupt cluster operations.
 nointr			Do not allow signals to interrupt cluster
 			operations.
+atime_quantum=60(*)	OCFS2 will not update atime unless this number
+			of seconds has passed since the last update.
+			Set to zero to always update atime.
diff --git a/Documentation/i2c/busses/i2c-amd8111 b/Documentation/i2c/busses/i2c-amd8111
index db294ee..460dd66 100644
--- a/Documentation/i2c/busses/i2c-amd8111
+++ b/Documentation/i2c/busses/i2c-amd8111
@@ -5,7 +5,7 @@
 
 Datasheets:
 	AMD datasheet not yet available, but almost everything can be found
-	in publically available ACPI 2.0 specification, which the adapter 
+	in the publicly available ACPI 2.0 specification, which the adapter
 	follows.
 
 Author: Vojtech Pavlik <vojtech@suse.cz>
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index e46c234..3db69a0 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -9,7 +9,10 @@
   * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
   * Intel 6300ESB
   * Intel 82801FB/FR/FW/FRW (ICH6)
-  * Intel ICH7
+  * Intel 82801G (ICH7)
+  * Intel 631xESB/632xESB (ESB2)
+  * Intel 82801H (ICH8)
+  * Intel ICH9
     Datasheets: Publicly available at the Intel website
 
 Authors: 
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index cd49c42..7f61fbc 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -10,11 +10,11 @@
   * nForce4 MCP51              10de:0264
   * nForce4 MCP55              10de:0368
 
-Datasheet: not publically available, but seems to be similar to the
+Datasheet: not publicly available, but seems to be similar to the
            AMD-8111 SMBus 2.0 adapter.
 
 Authors:
-	Hans-Frieder Vogt <hfvogt@arcor.de>, 
+	Hans-Frieder Vogt <hfvogt@gmx.net>,
 	Thomas Leibold <thomas@plx.com>, 
         Patrick Dreker <patrick@dreker.de>
 	
@@ -38,7 +38,7 @@
 -----
 
 The SMBus adapter in the nForce2 chipset seems to be very similar to the
-SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get
+SMBus 2.0 adapter in the AMD-8111 south bridge. However, I could only get
 the driver to work with direct I/O access, which is different to the EC
 interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the
 Asus A7N8X lists two SMBuses, both of which are supported by this driver.
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index dda1588..387482e 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -19,7 +19,8 @@
 
 It has a base protocol and pluggable congestion control IDs (CCIDs).
 
-It is at experimental RFC status and the homepage for DCCP as a protocol is at:
+It is at proposed standard RFC status and the homepage for DCCP as a protocol
+is at:
 	http://www.read.cs.ucla.edu/dccp/
 
 Missing features
@@ -34,9 +35,6 @@
 Socket options
 ==============
 
-DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for
-calculations.
-
 DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of
 service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,
 the socket will fall back to 0 (which means that no meaningful service code
diff --git a/MAINTAINERS b/MAINTAINERS
index b202493..8d16958 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -740,7 +740,7 @@
 M:	davej@codemonkey.org.uk
 L:	cpufreq@lists.linux.org.uk
 W:	http://www.codemonkey.org.uk/projects/cpufreq/
-T:	git kernel.org/pub/scm/linux/kernel/davej/cpufreq.git
+T:	git kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
 S:	Maintained
 
 CPUID/MSR DRIVER
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
index b457ca0..777564c 100644
--- a/arch/arm/mach-pnx4008/Makefile
+++ b/arch/arm/mach-pnx4008/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y			:= core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-y			:= core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
 obj-m			:=
 obj-n			:=
 obj-			:=
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
new file mode 100644
index 0000000..6f30882
--- /dev/null
+++ b/arch/arm/mach-pnx4008/i2c.c
@@ -0,0 +1,167 @@
+/*
+ * I2C initialization for PNX4008.
+ *
+ * Author: Vitaly Wool <vitalywool@gmail.com>
+ *
+ * 2005-2006 (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.
+ */
+
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c-pnx.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/i2c.h>
+
+static int set_clock_run(struct platform_device *pdev)
+{
+	struct clk *clk;
+	char name[10];
+	int retval = 0;
+
+	snprintf(name, 10, "i2c%d_ck", pdev->id);
+	clk = clk_get(&pdev->dev, name);
+	if (!IS_ERR(clk)) {
+		clk_set_rate(clk, 1);
+		clk_put(clk);
+	} else
+		retval = -ENOENT;
+
+	return retval;
+}
+
+static int set_clock_stop(struct platform_device *pdev)
+{
+	struct clk *clk;
+	char name[10];
+	int retval = 0;
+
+	snprintf(name, 10, "i2c%d_ck", pdev->id);
+	clk = clk_get(&pdev->dev, name);
+	if (!IS_ERR(clk)) {
+		clk_set_rate(clk, 0);
+		clk_put(clk);
+	} else
+		retval = -ENOENT;
+
+	return retval;
+}
+
+static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int retval = 0;
+#ifdef CONFIG_PM
+	retval = set_clock_run(pdev);
+#endif
+	return retval;
+}
+
+static int i2c_pnx_resume(struct platform_device *pdev)
+{
+	int retval = 0;
+#ifdef CONFIG_PM
+	retval = set_clock_run(pdev);
+#endif
+	return retval;
+}
+
+static u32 calculate_input_freq(struct platform_device *pdev)
+{
+	return HCLK_MHZ;
+}
+
+
+static struct i2c_pnx_algo_data pnx_algo_data0 = {
+	.base = PNX4008_I2C1_BASE,
+	.irq = I2C_1_INT,
+};
+
+static struct i2c_pnx_algo_data pnx_algo_data1 = {
+	.base = PNX4008_I2C2_BASE,
+	.irq = I2C_2_INT,
+};
+
+static struct i2c_pnx_algo_data pnx_algo_data2 = {
+	.base = (PNX4008_USB_CONFIG_BASE + 0x300),
+	.irq = USB_I2C_INT,
+};
+
+static struct i2c_adapter pnx_adapter0 = {
+	.name = I2C_CHIP_NAME "0",
+	.algo_data = &pnx_algo_data0,
+};
+static struct i2c_adapter pnx_adapter1 = {
+	.name = I2C_CHIP_NAME "1",
+	.algo_data = &pnx_algo_data1,
+};
+
+static struct i2c_adapter pnx_adapter2 = {
+	.name = "USB-I2C",
+	.algo_data = &pnx_algo_data2,
+};
+
+static struct i2c_pnx_data i2c0_data = {
+	.suspend = i2c_pnx_suspend,
+	.resume = i2c_pnx_resume,
+	.calculate_input_freq = calculate_input_freq,
+	.set_clock_run = set_clock_run,
+	.set_clock_stop = set_clock_stop,
+	.adapter = &pnx_adapter0,
+};
+
+static struct i2c_pnx_data i2c1_data = {
+	.suspend = i2c_pnx_suspend,
+	.resume = i2c_pnx_resume,
+	.calculate_input_freq = calculate_input_freq,
+	.set_clock_run = set_clock_run,
+	.set_clock_stop = set_clock_stop,
+	.adapter = &pnx_adapter1,
+};
+
+static struct i2c_pnx_data i2c2_data = {
+	.suspend = i2c_pnx_suspend,
+	.resume = i2c_pnx_resume,
+	.calculate_input_freq = calculate_input_freq,
+	.set_clock_run = set_clock_run,
+	.set_clock_stop = set_clock_stop,
+	.adapter = &pnx_adapter2,
+};
+
+static struct platform_device i2c0_device = {
+	.name = "pnx-i2c",
+	.id = 0,
+	.dev = {
+		.platform_data = &i2c0_data,
+	},
+};
+
+static struct platform_device i2c1_device = {
+	.name = "pnx-i2c",
+	.id = 1,
+	.dev = {
+		.platform_data = &i2c1_data,
+	},
+};
+
+static struct platform_device i2c2_device = {
+	.name = "pnx-i2c",
+	.id = 2,
+	.dev = {
+		.platform_data = &i2c2_data,
+	},
+};
+
+static struct platform_device *devices[] __initdata = {
+	&i2c0_device,
+	&i2c1_device,
+	&i2c2_device,
+};
+
+void __init pnx4008_register_i2c_devices(void)
+{
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 68c6705..84d3fe7 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -141,6 +141,19 @@
 	.resource	= realview_smc91x_resources,
 };
 
+static struct resource realview_i2c_resource = {
+	.start		= REALVIEW_I2C_BASE,
+	.end		= REALVIEW_I2C_BASE + SZ_4K - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+struct platform_device realview_i2c_device = {
+	.name		= "versatile-i2c",
+	.id		= -1,
+	.num_resources	= 1,
+	.resource	= &realview_i2c_resource,
+};
+
 #define REALVIEW_SYSMCI	(__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
 
 static unsigned int realview_mmc_status(struct device *dev)
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 93e86d9..2b53420 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -108,6 +108,7 @@
 
 extern struct platform_device realview_flash_device;
 extern struct platform_device realview_smc91x_device;
+extern struct platform_device realview_i2c_device;
 extern struct mmc_platform_data realview_mmc0_plat_data;
 extern struct mmc_platform_data realview_mmc1_plat_data;
 extern struct clk realview_clcd_clk;
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 84a9595..9741b4d 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -155,6 +155,7 @@
 
 	platform_device_register(&realview_flash_device);
 	platform_device_register(&realview_smc91x_device);
+	platform_device_register(&realview_i2c_device);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 5719694..bf71507c 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -325,6 +325,19 @@
 	.resource	= smc91x_resources,
 };
 
+static struct resource versatile_i2c_resource = {
+	.start			= VERSATILE_I2C_BASE,
+	.end			= VERSATILE_I2C_BASE + SZ_4K - 1,
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device versatile_i2c_device = {
+	.name			= "versatile-i2c",
+	.id			= -1,
+	.num_resources		= 1,
+	.resource		= &versatile_i2c_resource,
+};
+
 #define VERSATILE_SYSMCI	(__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
 
 unsigned int mmc_status(struct device *dev)
@@ -775,6 +788,7 @@
 	clk_register(&versatile_clcd_clk);
 
 	platform_device_register(&versatile_flash_device);
+	platform_device_register(&versatile_i2c_device);
 	platform_device_register(&smc91x_device);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index cced73c..32b361f 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -7,20 +7,83 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
 
+#include <asm/io.h>
+#include <asm/setup.h>
 #include <asm/arch/board.h>
 #include <asm/arch/init.h>
 
-struct eth_platform_data __initdata eth0_data = {
-	.valid		= 1,
-	.mii_phy_addr	= 0x10,
-	.is_rmii	= 0,
-	.hw_addr	= { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
+struct eth_addr {
+	u8 addr[6];
 };
 
+static struct eth_addr __initdata hw_addr[2];
+
+static struct eth_platform_data __initdata eth_data[2];
 extern struct lcdc_platform_data atstk1000_fb0_data;
 
+/*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+ * ethernet address. But we need to keep it around for a while until
+ * we can be reasonably sure the boot loader does this.
+ *
+ * The phy_id is ignored as the driver will probe for it.
+ */
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+	int i;
+
+	i = tag->u.ethernet.mac_index;
+	if (i < ARRAY_SIZE(hw_addr))
+		memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
+		       sizeof(hw_addr[i].addr));
+
+	return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+static void __init set_hw_addr(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	const u8 *addr;
+	void __iomem *regs;
+	struct clk *pclk;
+
+	if (!res)
+		return;
+	if (pdev->id >= ARRAY_SIZE(hw_addr))
+		return;
+
+	addr = hw_addr[pdev->id].addr;
+	if (!is_valid_ether_addr(addr))
+		return;
+
+	/*
+	 * Since this is board-specific code, we'll cheat and use the
+	 * physical address directly as we happen to know that it's
+	 * the same as the virtual address.
+	 */
+	regs = (void __iomem __force *)res->start;
+	pclk = clk_get(&pdev->dev, "pclk");
+	if (!pclk)
+		return;
+
+	clk_enable(pclk);
+	__raw_writel((addr[3] << 24) | (addr[2] << 16)
+		     | (addr[1] << 8) | addr[0], regs + 0x98);
+	__raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
+	clk_disable(pclk);
+	clk_put(pclk);
+}
+
 void __init setup_board(void)
 {
 	at32_map_usart(1, 0);	/* /dev/ttyS0 */
@@ -38,7 +101,8 @@
 	at32_add_device_usart(1);
 	at32_add_device_usart(2);
 
-	at32_add_device_eth(0, &eth0_data);
+	set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
+
 	at32_add_device_spi(0);
 	at32_add_device_lcdc(0, &atstk1000_fb0_data);
 
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
index 372e3f8..7c4c761 100644
--- a/arch/avr32/kernel/avr32_ksyms.c
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -7,12 +7,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/module.h>
 
 #include <asm/checksum.h>
 #include <asm/uaccess.h>
-#include <asm/delay.h>
 
 /*
  * GCC functions
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 317dc50..0b43259 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -38,6 +38,13 @@
 
 void machine_halt(void)
 {
+	/*
+	 * Enter Stop mode. The 32 kHz oscillator will keep running so
+	 * the RTC will keep the time properly and the system will
+	 * boot quickly.
+	 */
+	asm volatile("sleep 3\n\t"
+		     "sub pc, -2");
 }
 
 void machine_power_off(void)
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index ea2d1ff..a342116 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -229,30 +229,6 @@
 }
 __tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
 
-static int __init parse_tag_ethernet(struct tag *tag)
-{
-#if 0
-	const struct platform_device *pdev;
-
-	/*
-	 * We really need a bus type that supports "classes"...this
-	 * will do for now (until we must handle other kinds of
-	 * ethernet controllers)
-	 */
-	pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
-	if (pdev && pdev->dev.platform_data) {
-		struct eth_platform_data *data = pdev->dev.platform_data;
-
-		data->valid = 1;
-		data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
-		memcpy(data->hw_addr, tag->u.ethernet.hw_address,
-		       sizeof(data->hw_addr));
-	}
-#endif
-	return 0;
-}
-__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
-
 /*
  * Scan the tag table for this tag, and call its parse function. The
  * tag table is built by the linker from all the __tagtable
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
index 462c830..b3bc0b5 100644
--- a/arch/avr32/lib/delay.c
+++ b/arch/avr32/lib/delay.c
@@ -12,9 +12,9 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/param.h>
 #include <linux/types.h>
 
-#include <asm/delay.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 7ff6ad8..48f4ef3 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -11,6 +11,7 @@
 
 #include <asm/io.h>
 
+#include <asm/arch/at32ap7000.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
 #include <asm/arch/sm.h>
@@ -57,6 +58,9 @@
 	.num_resources	= ARRAY_SIZE(_name##_id##_resource),	\
 }
 
+#define select_peripheral(pin, periph, flags)			\
+	at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
+
 #define DEV_CLK(_name, devname, bus, _index)			\
 static struct clk devname##_##_name = {				\
 	.name		= #_name,				\
@@ -67,18 +71,6 @@
 	.index		= _index,				\
 }
 
-enum {
-	PIOA,
-	PIOB,
-	PIOC,
-	PIOD,
-};
-
-enum {
-	FUNC_A,
-	FUNC_B,
-};
-
 unsigned long at32ap7000_osc_rates[3] = {
 	[0] = 32768,
 	/* FIXME: these are ATSTK1002-specific */
@@ -569,26 +561,26 @@
 
 static inline void configure_usart0_pins(void)
 {
-	portmux_set_func(PIOA,  8, FUNC_B);	/* RXD	*/
-	portmux_set_func(PIOA,  9, FUNC_B);	/* TXD	*/
+	select_peripheral(PA(8),  PERIPH_B, 0);	/* RXD	*/
+	select_peripheral(PA(9),  PERIPH_B, 0);	/* TXD	*/
 }
 
 static inline void configure_usart1_pins(void)
 {
-	portmux_set_func(PIOA, 17, FUNC_A);	/* RXD	*/
-	portmux_set_func(PIOA, 18, FUNC_A);	/* TXD	*/
+	select_peripheral(PA(17), PERIPH_A, 0);	/* RXD	*/
+	select_peripheral(PA(18), PERIPH_A, 0);	/* TXD	*/
 }
 
 static inline void configure_usart2_pins(void)
 {
-	portmux_set_func(PIOB, 26, FUNC_B);	/* RXD	*/
-	portmux_set_func(PIOB, 27, FUNC_B);	/* TXD	*/
+	select_peripheral(PB(26), PERIPH_B, 0);	/* RXD	*/
+	select_peripheral(PB(27), PERIPH_B, 0);	/* TXD	*/
 }
 
 static inline void configure_usart3_pins(void)
 {
-	portmux_set_func(PIOB, 18, FUNC_B);	/* RXD	*/
-	portmux_set_func(PIOB, 17, FUNC_B);	/* TXD	*/
+	select_peripheral(PB(18), PERIPH_B, 0);	/* RXD	*/
+	select_peripheral(PB(17), PERIPH_B, 0);	/* TXD	*/
 }
 
 static struct platform_device *at32_usarts[4];
@@ -654,6 +646,15 @@
 DEV_CLK(hclk, macb0, hsb, 8);
 DEV_CLK(pclk, macb0, pbb, 6);
 
+static struct eth_platform_data macb1_data;
+static struct resource macb1_resource[] = {
+	PBMEM(0xfff01c00),
+	IRQ(26),
+};
+DEFINE_DEV_DATA(macb, 1);
+DEV_CLK(hclk, macb1, hsb, 9);
+DEV_CLK(pclk, macb1, pbb, 7);
+
 struct platform_device *__init
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
 {
@@ -663,27 +664,54 @@
 	case 0:
 		pdev = &macb0_device;
 
-		portmux_set_func(PIOC,  3, FUNC_A);	/* TXD0	*/
-		portmux_set_func(PIOC,  4, FUNC_A);	/* TXD1	*/
-		portmux_set_func(PIOC,  7, FUNC_A);	/* TXEN	*/
-		portmux_set_func(PIOC,  8, FUNC_A);	/* TXCK */
-		portmux_set_func(PIOC,  9, FUNC_A);	/* RXD0	*/
-		portmux_set_func(PIOC, 10, FUNC_A);	/* RXD1	*/
-		portmux_set_func(PIOC, 13, FUNC_A);	/* RXER	*/
-		portmux_set_func(PIOC, 15, FUNC_A);	/* RXDV	*/
-		portmux_set_func(PIOC, 16, FUNC_A);	/* MDC	*/
-		portmux_set_func(PIOC, 17, FUNC_A);	/* MDIO	*/
+		select_peripheral(PC(3),  PERIPH_A, 0);	/* TXD0	*/
+		select_peripheral(PC(4),  PERIPH_A, 0);	/* TXD1	*/
+		select_peripheral(PC(7),  PERIPH_A, 0);	/* TXEN	*/
+		select_peripheral(PC(8),  PERIPH_A, 0);	/* TXCK */
+		select_peripheral(PC(9),  PERIPH_A, 0);	/* RXD0	*/
+		select_peripheral(PC(10), PERIPH_A, 0);	/* RXD1	*/
+		select_peripheral(PC(13), PERIPH_A, 0);	/* RXER	*/
+		select_peripheral(PC(15), PERIPH_A, 0);	/* RXDV	*/
+		select_peripheral(PC(16), PERIPH_A, 0);	/* MDC	*/
+		select_peripheral(PC(17), PERIPH_A, 0);	/* MDIO	*/
 
 		if (!data->is_rmii) {
-			portmux_set_func(PIOC,  0, FUNC_A);	/* COL	*/
-			portmux_set_func(PIOC,  1, FUNC_A);	/* CRS	*/
-			portmux_set_func(PIOC,  2, FUNC_A);	/* TXER	*/
-			portmux_set_func(PIOC,  5, FUNC_A);	/* TXD2	*/
-			portmux_set_func(PIOC,  6, FUNC_A);	/* TXD3 */
-			portmux_set_func(PIOC, 11, FUNC_A);	/* RXD2	*/
-			portmux_set_func(PIOC, 12, FUNC_A);	/* RXD3	*/
-			portmux_set_func(PIOC, 14, FUNC_A);	/* RXCK	*/
-			portmux_set_func(PIOC, 18, FUNC_A);	/* SPD	*/
+			select_peripheral(PC(0),  PERIPH_A, 0);	/* COL	*/
+			select_peripheral(PC(1),  PERIPH_A, 0);	/* CRS	*/
+			select_peripheral(PC(2),  PERIPH_A, 0);	/* TXER	*/
+			select_peripheral(PC(5),  PERIPH_A, 0);	/* TXD2	*/
+			select_peripheral(PC(6),  PERIPH_A, 0);	/* TXD3 */
+			select_peripheral(PC(11), PERIPH_A, 0);	/* RXD2	*/
+			select_peripheral(PC(12), PERIPH_A, 0);	/* RXD3	*/
+			select_peripheral(PC(14), PERIPH_A, 0);	/* RXCK	*/
+			select_peripheral(PC(18), PERIPH_A, 0);	/* SPD	*/
+		}
+		break;
+
+	case 1:
+		pdev = &macb1_device;
+
+		select_peripheral(PD(13), PERIPH_B, 0);		/* TXD0	*/
+		select_peripheral(PD(14), PERIPH_B, 0);		/* TXD1	*/
+		select_peripheral(PD(11), PERIPH_B, 0);		/* TXEN	*/
+		select_peripheral(PD(12), PERIPH_B, 0);		/* TXCK */
+		select_peripheral(PD(10), PERIPH_B, 0);		/* RXD0	*/
+		select_peripheral(PD(6),  PERIPH_B, 0);		/* RXD1	*/
+		select_peripheral(PD(5),  PERIPH_B, 0);		/* RXER	*/
+		select_peripheral(PD(4),  PERIPH_B, 0);		/* RXDV	*/
+		select_peripheral(PD(3),  PERIPH_B, 0);		/* MDC	*/
+		select_peripheral(PD(2),  PERIPH_B, 0);		/* MDIO	*/
+
+		if (!data->is_rmii) {
+			select_peripheral(PC(19), PERIPH_B, 0);	/* COL	*/
+			select_peripheral(PC(23), PERIPH_B, 0);	/* CRS	*/
+			select_peripheral(PC(26), PERIPH_B, 0);	/* TXER	*/
+			select_peripheral(PC(27), PERIPH_B, 0);	/* TXD2	*/
+			select_peripheral(PC(28), PERIPH_B, 0);	/* TXD3 */
+			select_peripheral(PC(29), PERIPH_B, 0);	/* RXD2	*/
+			select_peripheral(PC(30), PERIPH_B, 0);	/* RXD3	*/
+			select_peripheral(PC(24), PERIPH_B, 0);	/* RXCK	*/
+			select_peripheral(PD(15), PERIPH_B, 0);	/* SPD	*/
 		}
 		break;
 
@@ -714,12 +742,12 @@
 	switch (id) {
 	case 0:
 		pdev = &spi0_device;
-		portmux_set_func(PIOA,  0, FUNC_A);	/* MISO	 */
-		portmux_set_func(PIOA,  1, FUNC_A);	/* MOSI	 */
-		portmux_set_func(PIOA,  2, FUNC_A);	/* SCK	 */
-		portmux_set_func(PIOA,  3, FUNC_A);	/* NPCS0 */
-		portmux_set_func(PIOA,  4, FUNC_A);	/* NPCS1 */
-		portmux_set_func(PIOA,  5, FUNC_A);	/* NPCS2 */
+		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 */
 		break;
 
 	default:
@@ -762,37 +790,37 @@
 	switch (id) {
 	case 0:
 		pdev = &lcdc0_device;
-		portmux_set_func(PIOC, 19, FUNC_A);	/* CC	  */
-		portmux_set_func(PIOC, 20, FUNC_A);	/* HSYNC  */
-		portmux_set_func(PIOC, 21, FUNC_A);	/* PCLK	  */
-		portmux_set_func(PIOC, 22, FUNC_A);	/* VSYNC  */
-		portmux_set_func(PIOC, 23, FUNC_A);	/* DVAL	  */
-		portmux_set_func(PIOC, 24, FUNC_A);	/* MODE	  */
-		portmux_set_func(PIOC, 25, FUNC_A);	/* PWR	  */
-		portmux_set_func(PIOC, 26, FUNC_A);	/* DATA0  */
-		portmux_set_func(PIOC, 27, FUNC_A);	/* DATA1  */
-		portmux_set_func(PIOC, 28, FUNC_A);	/* DATA2  */
-		portmux_set_func(PIOC, 29, FUNC_A);	/* DATA3  */
-		portmux_set_func(PIOC, 30, FUNC_A);	/* DATA4  */
-		portmux_set_func(PIOC, 31, FUNC_A);	/* DATA5  */
-		portmux_set_func(PIOD,  0, FUNC_A);	/* DATA6  */
-		portmux_set_func(PIOD,  1, FUNC_A);	/* DATA7  */
-		portmux_set_func(PIOD,  2, FUNC_A);	/* DATA8  */
-		portmux_set_func(PIOD,  3, FUNC_A);	/* DATA9  */
-		portmux_set_func(PIOD,  4, FUNC_A);	/* DATA10 */
-		portmux_set_func(PIOD,  5, FUNC_A);	/* DATA11 */
-		portmux_set_func(PIOD,  6, FUNC_A);	/* DATA12 */
-		portmux_set_func(PIOD,  7, FUNC_A);	/* DATA13 */
-		portmux_set_func(PIOD,  8, FUNC_A);	/* DATA14 */
-		portmux_set_func(PIOD,  9, FUNC_A);	/* DATA15 */
-		portmux_set_func(PIOD, 10, FUNC_A);	/* DATA16 */
-		portmux_set_func(PIOD, 11, FUNC_A);	/* DATA17 */
-		portmux_set_func(PIOD, 12, FUNC_A);	/* DATA18 */
-		portmux_set_func(PIOD, 13, FUNC_A);	/* DATA19 */
-		portmux_set_func(PIOD, 14, FUNC_A);	/* DATA20 */
-		portmux_set_func(PIOD, 15, FUNC_A);	/* DATA21 */
-		portmux_set_func(PIOD, 16, FUNC_A);	/* DATA22 */
-		portmux_set_func(PIOD, 17, FUNC_A);	/* DATA23 */
+		select_peripheral(PC(19), PERIPH_A, 0);	/* CC	  */
+		select_peripheral(PC(20), PERIPH_A, 0);	/* HSYNC  */
+		select_peripheral(PC(21), PERIPH_A, 0);	/* PCLK	  */
+		select_peripheral(PC(22), PERIPH_A, 0);	/* VSYNC  */
+		select_peripheral(PC(23), PERIPH_A, 0);	/* DVAL	  */
+		select_peripheral(PC(24), PERIPH_A, 0);	/* MODE	  */
+		select_peripheral(PC(25), PERIPH_A, 0);	/* PWR	  */
+		select_peripheral(PC(26), PERIPH_A, 0);	/* DATA0  */
+		select_peripheral(PC(27), PERIPH_A, 0);	/* DATA1  */
+		select_peripheral(PC(28), PERIPH_A, 0);	/* DATA2  */
+		select_peripheral(PC(29), PERIPH_A, 0);	/* DATA3  */
+		select_peripheral(PC(30), PERIPH_A, 0);	/* DATA4  */
+		select_peripheral(PC(31), PERIPH_A, 0);	/* DATA5  */
+		select_peripheral(PD(0),  PERIPH_A, 0);	/* DATA6  */
+		select_peripheral(PD(1),  PERIPH_A, 0);	/* DATA7  */
+		select_peripheral(PD(2),  PERIPH_A, 0);	/* DATA8  */
+		select_peripheral(PD(3),  PERIPH_A, 0);	/* DATA9  */
+		select_peripheral(PD(4),  PERIPH_A, 0);	/* DATA10 */
+		select_peripheral(PD(5),  PERIPH_A, 0);	/* DATA11 */
+		select_peripheral(PD(6),  PERIPH_A, 0);	/* DATA12 */
+		select_peripheral(PD(7),  PERIPH_A, 0);	/* DATA13 */
+		select_peripheral(PD(8),  PERIPH_A, 0);	/* DATA14 */
+		select_peripheral(PD(9),  PERIPH_A, 0);	/* DATA15 */
+		select_peripheral(PD(10), PERIPH_A, 0);	/* DATA16 */
+		select_peripheral(PD(11), PERIPH_A, 0);	/* DATA17 */
+		select_peripheral(PD(12), PERIPH_A, 0);	/* DATA18 */
+		select_peripheral(PD(13), PERIPH_A, 0);	/* DATA19 */
+		select_peripheral(PD(14), PERIPH_A, 0);	/* DATA20 */
+		select_peripheral(PD(15), PERIPH_A, 0);	/* DATA21 */
+		select_peripheral(PD(16), PERIPH_A, 0);	/* DATA22 */
+		select_peripheral(PD(17), PERIPH_A, 0);	/* DATA23 */
 
 		clk_set_parent(&lcdc0_pixclk, &pll0);
 		clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
@@ -838,6 +866,8 @@
 	&atmel_usart3_usart,
 	&macb0_hclk,
 	&macb0_pclk,
+	&macb1_hclk,
+	&macb1_pclk,
 	&spi0_mck,
 	&lcdc0_hclk,
 	&lcdc0_pixclk,
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index 4dff1f9..b59272e 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -49,12 +49,25 @@
 static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
 {
 	struct at32_sm *sm = get_irq_chip_data(irq);
+	struct irq_desc *desc;
 	unsigned int i = irq - sm->eim_first_irq;
 	u32 mode, edge, level;
 	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);
 
@@ -148,10 +161,15 @@
 	pattern = sm_readl(sm, EIM_MODE);
 	nr_irqs = fls(pattern);
 
+	/* Trigger on falling edge unless overridden by driver */
+	sm_writel(sm, EIM_MODE, 0UL);
+	sm_writel(sm, EIM_EDGE, 0UL);
+
 	sm->eim_chip = &eim_chip;
 
 	for (i = 0; i < nr_irqs; i++) {
-		set_irq_chip(sm->eim_first_irq + i, &eim_chip);
+		set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
+					 handle_edge_irq);
 		set_irq_chip_data(sm->eim_first_irq + i, sm);
 	}
 
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index eb87a18..dd5c009 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -136,3 +136,7 @@
 	panic("Interrupt controller initialization failed!\n");
 }
 
+unsigned long intc_get_pending(int group)
+{
+	return intc_readl(&intc0, INTREQ0 + 4 * group);
+}
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d3aabfc..f1280ed 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -25,27 +25,98 @@
 	void __iomem *regs;
 	const struct platform_device *pdev;
 	struct clk *clk;
-	u32 alloc_mask;
+	u32 pinmux_mask;
 	char name[32];
 };
 
 static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-		      unsigned int function_id)
+static struct pio_device *gpio_to_pio(unsigned int gpio)
 {
 	struct pio_device *pio;
-	u32 mask = 1 << pin_id;
+	unsigned int index;
 
-	BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
+	index = gpio >> 5;
+	if (index >= MAX_NR_PIO_DEVICES)
+		return NULL;
+	pio = &pio_dev[index];
+	if (!pio->regs)
+		return NULL;
 
-	pio = &pio_dev[portmux_id];
+	return pio;
+}
 
-	if (function_id)
+/* Pin multiplexing API */
+
+void __init at32_select_periph(unsigned int pin, unsigned int periph,
+			       unsigned long flags)
+{
+	struct pio_device *pio;
+	unsigned int pin_index = pin & 0x1f;
+	u32 mask = 1 << pin_index;
+
+	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;
+	}
+
+	pio_writel(pio, PUER, mask);
+	if (periph)
 		pio_writel(pio, BSR, mask);
 	else
 		pio_writel(pio, ASR, mask);
+
 	pio_writel(pio, PDR, mask);
+	if (!(flags & AT32_GPIOF_PULLUP))
+		pio_writel(pio, PUDR, mask);
+
+	return;
+
+fail:
+	dump_stack();
+}
+
+void __init at32_select_gpio(unsigned int pin, unsigned long flags)
+{
+	struct pio_device *pio;
+	unsigned int pin_index = pin & 0x1f;
+	u32 mask = 1 << pin_index;
+
+	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;
+	}
+
+	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)
+		pio_writel(pio, OER, mask);
+	else
+		pio_writel(pio, ODR, mask);
+
+	pio_writel(pio, PER, mask);
+	if (!(flags & AT32_GPIOF_PULLUP))
+		pio_writel(pio, PUDR, mask);
+
+	return;
+
+fail:
+	dump_stack();
 }
 
 static int __init pio_probe(struct platform_device *pdev)
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
deleted file mode 100644
index 03306eb..0000000
--- a/arch/avr32/mach-at32ap/sm.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * System Manager driver for AT32AP CPUs
- *
- * 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/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-
-#include <asm/intc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/sm.h>
-
-#include "sm.h"
-
-#define SM_EIM_IRQ_RESOURCE	1
-#define SM_PM_IRQ_RESOURCE	2
-#define SM_RTC_IRQ_RESOURCE	3
-
-#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
-
-struct at32_sm system_manager;
-
-int __init at32_sm_init(void)
-{
-	struct resource *regs;
-	struct at32_sm *sm = &system_manager;
-	int ret = -ENXIO;
-
-	regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
-	if (!regs)
-		goto fail;
-
-	spin_lock_init(&sm->lock);
-	sm->pdev = &at32_sm_device;
-
-	ret = -ENOMEM;
-	sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
-	if (!sm->regs)
-		goto fail;
-
-	return 0;
-
-fail:
-	printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
-	return ret;
-}
-
-/*
- * External Interrupt Module (EIM).
- *
- * EIM gets level- or edge-triggered interrupts of either polarity
- * from the outside and converts it to active-high level-triggered
- * interrupts that the internal interrupt controller can handle. EIM
- * also provides masking/unmasking of interrupts, as well as
- * acknowledging of edge-triggered interrupts.
- */
-
-static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
-					  struct pt_regs *regs)
-{
-	printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
-	disable_irq(irq);
-	return IRQ_NONE;
-}
-
-static struct irqaction eim_spurious_action = {
-	.handler = spurious_eim_interrupt,
-};
-
-static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct irq_controller * irqc = dev_id;
-	struct at32_sm *sm = to_eim(irqc);
-	unsigned long pending;
-
-	/*
-	 * No need to disable interrupts globally.  The interrupt
-	 * level relevant to this group must be masked all the time,
-	 * so we know that this particular EIM instance will not be
-	 * re-entered.
-	 */
-	spin_lock(&sm->lock);
-
-	pending = intc_get_pending(sm->irqc.irq_group);
-	if (unlikely(!pending)) {
-		printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
-		       sm->irqc.irq_group);
-		goto unlock;
-	}
-
-	do {
-		struct irqaction *action;
-		unsigned int i;
-
-		i = fls(pending) - 1;
-		pending &= ~(1 << i);
-		action = sm->action[i];
-
-		/* Acknowledge the interrupt */
-		sm_writel(sm, EIM_ICR, 1 << i);
-
-		spin_unlock(&sm->lock);
-
-		if (action->flags & SA_INTERRUPT)
-			local_irq_disable();
-		action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
-		local_irq_enable();
-		spin_lock(&sm->lock);
-		if (action->flags & SA_SAMPLE_RANDOM)
-			add_interrupt_randomness(sm->irqc.first_irq + i);
-	} while (pending);
-
-unlock:
-	spin_unlock(&sm->lock);
-	return IRQ_HANDLED;
-}
-
-static void eim_mask(struct irq_controller *irqc, unsigned int irq)
-{
-	struct at32_sm *sm = to_eim(irqc);
-	unsigned int i;
-
-	i = irq - sm->irqc.first_irq;
-	sm_writel(sm, EIM_IDR, 1 << i);
-}
-
-static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
-{
-	struct at32_sm *sm = to_eim(irqc);
-	unsigned int i;
-
-	i = irq - sm->irqc.first_irq;
-	sm_writel(sm, EIM_IER, 1 << i);
-}
-
-static int eim_setup(struct irq_controller *irqc, unsigned int irq,
-		struct irqaction *action)
-{
-	struct at32_sm *sm = to_eim(irqc);
-	sm->action[irq - sm->irqc.first_irq] = action;
-	/* Acknowledge earlier interrupts */
-	sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
-	eim_unmask(irqc, irq);
-	return 0;
-}
-
-static void eim_free(struct irq_controller *irqc, unsigned int irq,
-		void *dev)
-{
-	struct at32_sm *sm = to_eim(irqc);
-	eim_mask(irqc, irq);
-	sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
-}
-
-static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
-			unsigned int type)
-{
-	struct at32_sm *sm = to_eim(irqc);
-	unsigned long flags;
-	u32 value, pattern;
-
-	spin_lock_irqsave(&sm->lock, flags);
-
-	pattern = 1 << (irq - sm->irqc.first_irq);
-
-	value = sm_readl(sm, EIM_MODE);
-	if (type & IRQ_TYPE_LEVEL)
-		value |= pattern;
-	else
-		value &= ~pattern;
-	sm_writel(sm, EIM_MODE, value);
-	value = sm_readl(sm, EIM_EDGE);
-	if (type & IRQ_EDGE_RISING)
-		value |= pattern;
-	else
-		value &= ~pattern;
-	sm_writel(sm, EIM_EDGE, value);
-	value = sm_readl(sm, EIM_LEVEL);
-	if (type & IRQ_LEVEL_HIGH)
-		value |= pattern;
-	else
-		value &= ~pattern;
-	sm_writel(sm, EIM_LEVEL, value);
-
-	spin_unlock_irqrestore(&sm->lock, flags);
-
-	return 0;
-}
-
-static unsigned int eim_get_type(struct irq_controller *irqc,
-				 unsigned int irq)
-{
-	struct at32_sm *sm = to_eim(irqc);
-	unsigned long flags;
-	unsigned int type = 0;
-	u32 mode, edge, level, pattern;
-
-	pattern = 1 << (irq - sm->irqc.first_irq);
-
-	spin_lock_irqsave(&sm->lock, flags);
-	mode = sm_readl(sm, EIM_MODE);
-	edge = sm_readl(sm, EIM_EDGE);
-	level = sm_readl(sm, EIM_LEVEL);
-	spin_unlock_irqrestore(&sm->lock, flags);
-
-	if (mode & pattern)
-		type |= IRQ_TYPE_LEVEL;
-	if (edge & pattern)
-		type |= IRQ_EDGE_RISING;
-	if (level & pattern)
-		type |= IRQ_LEVEL_HIGH;
-
-	return type;
-}
-
-static struct irq_controller_class eim_irq_class = {
-	.typename	= "EIM",
-	.handle		= eim_handle_irq,
-	.setup		= eim_setup,
-	.free		= eim_free,
-	.mask		= eim_mask,
-	.unmask		= eim_unmask,
-	.set_type	= eim_set_type,
-	.get_type	= eim_get_type,
-};
-
-static int __init eim_init(void)
-{
-	struct at32_sm *sm = &system_manager;
-	unsigned int i;
-	u32 pattern;
-	int ret;
-
-	/*
-	 * The EIM is really the same module as SM, so register
-	 * mapping, etc. has been taken care of already.
-	 */
-
-	/*
-	 * Find out how many interrupt lines that are actually
-	 * implemented in hardware.
-	 */
-	sm_writel(sm, EIM_IDR, ~0UL);
-	sm_writel(sm, EIM_MODE, ~0UL);
-	pattern = sm_readl(sm, EIM_MODE);
-	sm->irqc.nr_irqs = fls(pattern);
-
-	ret = -ENOMEM;
-	sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
-			     GFP_KERNEL);
-	if (!sm->action)
-		goto out;
-
-	for (i = 0; i < sm->irqc.nr_irqs; i++)
-		sm->action[i] = &eim_spurious_action;
-
-	spin_lock_init(&sm->lock);
-	sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
-	sm->irqc.class = &eim_irq_class;
-
-	ret = intc_register_controller(&sm->irqc);
-	if (ret < 0)
-		goto out_free_actions;
-
-	printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
-	       sm->regs, sm->irqc.irq_group);
-	printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
-	       sm->irqc.nr_irqs, sm->irqc.first_irq);
-
-	return 0;
-
-out_free_actions:
-	kfree(sm->action);
-out:
-	return ret;
-}
-arch_initcall(eim_init);
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index ccc1edf..5299c5b 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -17,6 +17,7 @@
 	help
 	  This driver adds a CPUFreq driver which utilizes the ACPI
 	  Processor Performance States.
+	  This driver also supports Intel Enhanced Speedstep.
 
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
@@ -121,11 +122,14 @@
 	  If in doubt, say N.
 
 config X86_SPEEDSTEP_CENTRINO_ACPI
-	bool "Use ACPI tables to decode valid frequency/voltage pairs"
+	bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
 	depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
 	depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
 	default y
 	help
+	  This is deprecated and this functionality is now merged into
+	  acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
+	  speedstep_centrino.
 	  Use primarily the information provided in the BIOS ACPI tables
 	  to determine valid CPU frequency and voltage pairings. It is
 	  required for the driver to work on non-Banias CPUs.
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
index 2e894f1..8de3abe 100644
--- a/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -7,9 +7,9 @@
 obj-$(CONFIG_X86_LONGRUN)		+= longrun.o  
 obj-$(CONFIG_X86_GX_SUSPMOD)		+= gx-suspmod.o
 obj-$(CONFIG_X86_SPEEDSTEP_ICH)		+= speedstep-ich.o
-obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)	+= speedstep-centrino.o
 obj-$(CONFIG_X86_SPEEDSTEP_LIB)		+= speedstep-lib.o
 obj-$(CONFIG_X86_SPEEDSTEP_SMI)		+= speedstep-smi.o
 obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)	+= speedstep-centrino.o
 obj-$(CONFIG_X86_P4_CLOCKMOD)		+= p4-clockmod.o
 obj-$(CONFIG_X86_CPUFREQ_NFORCE2)	+= cpufreq-nforce2.o
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 57c880b..18f4715 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -1,9 +1,10 @@
 /*
- * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $)
+ * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.4 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *  Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
+ *  Copyright (C) 2006       Denis Sadykov <denis.m.sadykov@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -27,202 +28,387 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
 #include <linux/cpufreq.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/compiler.h>
-#include <linux/sched.h>	/* current */
 #include <linux/dmi.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
 
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
 
 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
 MODULE_LICENSE("GPL");
 
-
-struct cpufreq_acpi_io {
-	struct acpi_processor_performance	*acpi_data;
-	struct cpufreq_frequency_table		*freq_table;
-	unsigned int				resume;
+enum {
+	UNDEFINED_CAPABLE = 0,
+	SYSTEM_INTEL_MSR_CAPABLE,
+	SYSTEM_IO_CAPABLE,
 };
 
-static struct cpufreq_acpi_io	*acpi_io_data[NR_CPUS];
-static struct acpi_processor_performance	*acpi_perf_data[NR_CPUS];
+#define INTEL_MSR_RANGE		(0xffff)
+#define CPUID_6_ECX_APERFMPERF_CAPABILITY	(0x1)
+
+struct acpi_cpufreq_data {
+	struct acpi_processor_performance *acpi_data;
+	struct cpufreq_frequency_table *freq_table;
+	unsigned int max_freq;
+	unsigned int resume;
+	unsigned int cpu_feature;
+};
+
+static struct acpi_cpufreq_data *drv_data[NR_CPUS];
+static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
 
 static struct cpufreq_driver acpi_cpufreq_driver;
 
 static unsigned int acpi_pstate_strict;
 
-static int
-acpi_processor_write_port(
-	u16	port,
-	u8	bit_width,
-	u32	value)
+static int check_est_cpu(unsigned int cpuid)
 {
-	if (bit_width <= 8) {
-		outb(value, port);
-	} else if (bit_width <= 16) {
-		outw(value, port);
-	} else if (bit_width <= 32) {
-		outl(value, port);
-	} else {
-		return -ENODEV;
+	struct cpuinfo_x86 *cpu = &cpu_data[cpuid];
+
+	if (cpu->x86_vendor != X86_VENDOR_INTEL ||
+	    !cpu_has(cpu, X86_FEATURE_EST))
+		return 0;
+
+	return 1;
+}
+
+static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
+{
+	struct acpi_processor_performance *perf;
+	int i;
+
+	perf = data->acpi_data;
+
+	for (i=0; i<perf->state_count; i++) {
+		if (value == perf->states[i].status)
+			return data->freq_table[i].frequency;
 	}
 	return 0;
 }
 
-static int
-acpi_processor_read_port(
-	u16	port,
-	u8	bit_width,
-	u32	*ret)
+static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
+{
+	int i;
+	struct acpi_processor_performance *perf;
+
+	msr &= INTEL_MSR_RANGE;
+	perf = data->acpi_data;
+
+	for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+		if (msr == perf->states[data->freq_table[i].index].status)
+			return data->freq_table[i].frequency;
+	}
+	return data->freq_table[0].frequency;
+}
+
+static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
+{
+	switch (data->cpu_feature) {
+	case SYSTEM_INTEL_MSR_CAPABLE:
+		return extract_msr(val, data);
+	case SYSTEM_IO_CAPABLE:
+		return extract_io(val, data);
+	default:
+		return 0;
+	}
+}
+
+static void wrport(u16 port, u8 bit_width, u32 value)
+{
+	if (bit_width <= 8)
+		outb(value, port);
+	else if (bit_width <= 16)
+		outw(value, port);
+	else if (bit_width <= 32)
+		outl(value, port);
+}
+
+static void rdport(u16 port, u8 bit_width, u32 * ret)
 {
 	*ret = 0;
-	if (bit_width <= 8) {
+	if (bit_width <= 8)
 		*ret = inb(port);
-	} else if (bit_width <= 16) {
+	else if (bit_width <= 16)
 		*ret = inw(port);
-	} else if (bit_width <= 32) {
+	else if (bit_width <= 32)
 		*ret = inl(port);
-	} else {
-		return -ENODEV;
+}
+
+struct msr_addr {
+	u32 reg;
+};
+
+struct io_addr {
+	u16 port;
+	u8 bit_width;
+};
+
+typedef union {
+	struct msr_addr msr;
+	struct io_addr io;
+} drv_addr_union;
+
+struct drv_cmd {
+	unsigned int type;
+	cpumask_t mask;
+	drv_addr_union addr;
+	u32 val;
+};
+
+static void do_drv_read(struct drv_cmd *cmd)
+{
+	u32 h;
+
+	switch (cmd->type) {
+	case SYSTEM_INTEL_MSR_CAPABLE:
+		rdmsr(cmd->addr.msr.reg, cmd->val, h);
+		break;
+	case SYSTEM_IO_CAPABLE:
+		rdport(cmd->addr.io.port, cmd->addr.io.bit_width, &cmd->val);
+		break;
+	default:
+		break;
+	}
+}
+
+static void do_drv_write(struct drv_cmd *cmd)
+{
+	u32 h = 0;
+
+	switch (cmd->type) {
+	case SYSTEM_INTEL_MSR_CAPABLE:
+		wrmsr(cmd->addr.msr.reg, cmd->val, h);
+		break;
+	case SYSTEM_IO_CAPABLE:
+		wrport(cmd->addr.io.port, cmd->addr.io.bit_width, cmd->val);
+		break;
+	default:
+		break;
+	}
+}
+
+static void drv_read(struct drv_cmd *cmd)
+{
+	cpumask_t saved_mask = current->cpus_allowed;
+	cmd->val = 0;
+
+	set_cpus_allowed(current, cmd->mask);
+	do_drv_read(cmd);
+	set_cpus_allowed(current, saved_mask);
+}
+
+static void drv_write(struct drv_cmd *cmd)
+{
+	cpumask_t saved_mask = current->cpus_allowed;
+	unsigned int i;
+
+	for_each_cpu_mask(i, cmd->mask) {
+		set_cpus_allowed(current, cpumask_of_cpu(i));
+		do_drv_write(cmd);
+	}
+
+	set_cpus_allowed(current, saved_mask);
+	return;
+}
+
+static u32 get_cur_val(cpumask_t mask)
+{
+	struct acpi_processor_performance *perf;
+	struct drv_cmd cmd;
+
+	if (unlikely(cpus_empty(mask)))
+		return 0;
+
+	switch (drv_data[first_cpu(mask)]->cpu_feature) {
+	case SYSTEM_INTEL_MSR_CAPABLE:
+		cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
+		cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
+		break;
+	case SYSTEM_IO_CAPABLE:
+		cmd.type = SYSTEM_IO_CAPABLE;
+		perf = drv_data[first_cpu(mask)]->acpi_data;
+		cmd.addr.io.port = perf->control_register.address;
+		cmd.addr.io.bit_width = perf->control_register.bit_width;
+		break;
+	default:
+		return 0;
+	}
+
+	cmd.mask = mask;
+
+	drv_read(&cmd);
+
+	dprintk("get_cur_val = %u\n", cmd.val);
+
+	return cmd.val;
+}
+
+/*
+ * Return the measured active (C0) frequency on this CPU since last call
+ * to this function.
+ * Input: cpu number
+ * Return: Average CPU frequency in terms of max frequency (zero on error)
+ *
+ * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
+ * over a period of time, while CPU is in C0 state.
+ * IA32_MPERF counts at the rate of max advertised frequency
+ * IA32_APERF counts at the rate of actual CPU frequency
+ * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
+ * no meaning should be associated with absolute values of these MSRs.
+ */
+static unsigned int get_measured_perf(unsigned int cpu)
+{
+	union {
+		struct {
+			u32 lo;
+			u32 hi;
+		} split;
+		u64 whole;
+	} aperf_cur, mperf_cur;
+
+	cpumask_t saved_mask;
+	unsigned int perf_percent;
+	unsigned int retval;
+
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	if (get_cpu() != cpu) {
+		/* We were not able to run on requested processor */
+		put_cpu();
+		return 0;
+	}
+
+	rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
+	rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
+
+	wrmsr(MSR_IA32_APERF, 0,0);
+	wrmsr(MSR_IA32_MPERF, 0,0);
+
+#ifdef __i386__
+	/*
+	 * We dont want to do 64 bit divide with 32 bit kernel
+	 * Get an approximate value. Return failure in case we cannot get
+	 * an approximate value.
+	 */
+	if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) {
+		int shift_count;
+		u32 h;
+
+		h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi);
+		shift_count = fls(h);
+
+		aperf_cur.whole >>= shift_count;
+		mperf_cur.whole >>= shift_count;
+	}
+
+	if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) {
+		int shift_count = 7;
+		aperf_cur.split.lo >>= shift_count;
+		mperf_cur.split.lo >>= shift_count;
+	}
+
+	if (aperf_cur.split.lo && mperf_cur.split.lo)
+		perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo;
+	else
+		perf_percent = 0;
+
+#else
+	if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
+		int shift_count = 7;
+		aperf_cur.whole >>= shift_count;
+		mperf_cur.whole >>= shift_count;
+	}
+
+	if (aperf_cur.whole && mperf_cur.whole)
+		perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole;
+	else
+		perf_percent = 0;
+
+#endif
+
+	retval = drv_data[cpu]->max_freq * perf_percent / 100;
+
+	put_cpu();
+	set_cpus_allowed(current, saved_mask);
+
+	dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
+	return retval;
+}
+
+static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
+{
+	struct acpi_cpufreq_data *data = drv_data[cpu];
+	unsigned int freq;
+
+	dprintk("get_cur_freq_on_cpu (%d)\n", cpu);
+
+	if (unlikely(data == NULL ||
+		     data->acpi_data == NULL || data->freq_table == NULL)) {
+		return 0;
+	}
+
+	freq = extract_freq(get_cur_val(cpumask_of_cpu(cpu)), data);
+	dprintk("cur freq = %u\n", freq);
+
+	return freq;
+}
+
+static unsigned int check_freqs(cpumask_t mask, unsigned int freq,
+				struct acpi_cpufreq_data *data)
+{
+	unsigned int cur_freq;
+	unsigned int i;
+
+	for (i=0; i<100; i++) {
+		cur_freq = extract_freq(get_cur_val(mask), data);
+		if (cur_freq == freq)
+			return 1;
+		udelay(10);
 	}
 	return 0;
 }
 
-static int
-acpi_processor_set_performance (
-	struct cpufreq_acpi_io	*data,
-	unsigned int		cpu,
-	int			state)
+static int acpi_cpufreq_target(struct cpufreq_policy *policy,
+			       unsigned int target_freq, unsigned int relation)
 {
-	u16			port = 0;
-	u8			bit_width = 0;
-	int			i = 0;
-	int			ret = 0;
-	u32			value = 0;
-	int			retval;
-	struct acpi_processor_performance	*perf;
-
-	dprintk("acpi_processor_set_performance\n");
-
-	retval = 0;
-	perf = data->acpi_data;	
-	if (state == perf->state) {
-		if (unlikely(data->resume)) {
-			dprintk("Called after resume, resetting to P%d\n", state);
-			data->resume = 0;
-		} else {
-			dprintk("Already at target state (P%d)\n", state);
-			return (retval);
-		}
-	}
-
-	dprintk("Transitioning from P%d to P%d\n", perf->state, state);
-
-	/*
-	 * First we write the target state's 'control' value to the
-	 * control_register.
-	 */
-
-	port = perf->control_register.address;
-	bit_width = perf->control_register.bit_width;
-	value = (u32) perf->states[state].control;
-
-	dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
-
-	ret = acpi_processor_write_port(port, bit_width, value);
-	if (ret) {
-		dprintk("Invalid port width 0x%04x\n", bit_width);
-		return (ret);
-	}
-
-	/*
-	 * Assume the write went through when acpi_pstate_strict is not used.
-	 * As read status_register is an expensive operation and there 
-	 * are no specific error cases where an IO port write will fail.
-	 */
-	if (acpi_pstate_strict) {
-		/* Then we read the 'status_register' and compare the value 
-		 * with the target state's 'status' to make sure the 
-		 * transition was successful.
-		 * Note that we'll poll for up to 1ms (100 cycles of 10us) 
-		 * before giving up.
-		 */
-
-		port = perf->status_register.address;
-		bit_width = perf->status_register.bit_width;
-
-		dprintk("Looking for 0x%08x from port 0x%04x\n",
-			(u32) perf->states[state].status, port);
-
-		for (i = 0; i < 100; i++) {
-			ret = acpi_processor_read_port(port, bit_width, &value);
-			if (ret) {	
-				dprintk("Invalid port width 0x%04x\n", bit_width);
-				return (ret);
-			}
-			if (value == (u32) perf->states[state].status)
-				break;
-			udelay(10);
-		}
-	} else {
-		value = (u32) perf->states[state].status;
-	}
-
-	if (unlikely(value != (u32) perf->states[state].status)) {
-		printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
-		retval = -ENODEV;
-		return (retval);
-	}
-
-	dprintk("Transition successful after %d microseconds\n", i * 10);
-
-	perf->state = state;
-	return (retval);
-}
-
-
-static int
-acpi_cpufreq_target (
-	struct cpufreq_policy   *policy,
-	unsigned int target_freq,
-	unsigned int relation)
-{
-	struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+	struct acpi_cpufreq_data *data = drv_data[policy->cpu];
 	struct acpi_processor_performance *perf;
 	struct cpufreq_freqs freqs;
 	cpumask_t online_policy_cpus;
-	cpumask_t saved_mask;
-	cpumask_t set_mask;
-	cpumask_t covered_cpus;
-	unsigned int cur_state = 0;
+	struct drv_cmd cmd;
+	unsigned int msr;
 	unsigned int next_state = 0;
-	unsigned int result = 0;
-	unsigned int j;
-	unsigned int tmp;
+	unsigned int next_perf_state = 0;
+	unsigned int i;
+	int result = 0;
 
-	dprintk("acpi_cpufreq_setpolicy\n");
+	dprintk("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
 
-	result = cpufreq_frequency_table_target(policy,
-			data->freq_table,
-			target_freq,
-			relation,
-			&next_state);
-	if (unlikely(result))
-		return (result);
+	if (unlikely(data == NULL ||
+	     data->acpi_data == NULL || data->freq_table == NULL)) {
+		return -ENODEV;
+	}
 
 	perf = data->acpi_data;
-	cur_state = perf->state;
-	freqs.old = data->freq_table[cur_state].frequency;
-	freqs.new = data->freq_table[next_state].frequency;
+	result = cpufreq_frequency_table_target(policy,
+						data->freq_table,
+						target_freq,
+						relation, &next_state);
+	if (unlikely(result))
+		return -ENODEV;
 
 #ifdef CONFIG_HOTPLUG_CPU
 	/* cpufreq holds the hotplug lock, so we are safe from here on */
@@ -231,106 +417,84 @@
 	online_policy_cpus = policy->cpus;
 #endif
 
-	for_each_cpu_mask(j, online_policy_cpus) {
-		freqs.cpu = j;
+	next_perf_state = data->freq_table[next_state].index;
+	if (perf->state == next_perf_state) {
+		if (unlikely(data->resume)) {
+			dprintk("Called after resume, resetting to P%d\n",
+				next_perf_state);
+			data->resume = 0;
+		} else {
+			dprintk("Already at target state (P%d)\n",
+				next_perf_state);
+			return 0;
+		}
+	}
+
+	switch (data->cpu_feature) {
+	case SYSTEM_INTEL_MSR_CAPABLE:
+		cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
+		cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
+		msr =
+		    (u32) perf->states[next_perf_state].
+		    control & INTEL_MSR_RANGE;
+		cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr;
+		break;
+	case SYSTEM_IO_CAPABLE:
+		cmd.type = SYSTEM_IO_CAPABLE;
+		cmd.addr.io.port = perf->control_register.address;
+		cmd.addr.io.bit_width = perf->control_register.bit_width;
+		cmd.val = (u32) perf->states[next_perf_state].control;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	cpus_clear(cmd.mask);
+
+	if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY)
+		cmd.mask = online_policy_cpus;
+	else
+		cpu_set(policy->cpu, cmd.mask);
+
+	freqs.old = data->freq_table[perf->state].frequency;
+	freqs.new = data->freq_table[next_perf_state].frequency;
+	for_each_cpu_mask(i, cmd.mask) {
+		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	}
 
-	/*
-	 * We need to call driver->target() on all or any CPU in
-	 * policy->cpus, depending on policy->shared_type.
-	 */
-	saved_mask = current->cpus_allowed;
-	cpus_clear(covered_cpus);
-	for_each_cpu_mask(j, online_policy_cpus) {
-		/*
-		 * Support for SMP systems.
-		 * Make sure we are running on CPU that wants to change freq
-		 */
-		cpus_clear(set_mask);
-		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
-			cpus_or(set_mask, set_mask, online_policy_cpus);
-		else
-			cpu_set(j, set_mask);
+	drv_write(&cmd);
 
-		set_cpus_allowed(current, set_mask);
-		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
-			dprintk("couldn't limit to CPUs in this domain\n");
-			result = -EAGAIN;
-			break;
+	if (acpi_pstate_strict) {
+		if (!check_freqs(cmd.mask, freqs.new, data)) {
+			dprintk("acpi_cpufreq_target failed (%d)\n",
+				policy->cpu);
+			return -EAGAIN;
 		}
-
-		result = acpi_processor_set_performance (data, j, next_state);
-		if (result) {
-			result = -EAGAIN;
-			break;
-		}
-
-		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
-			break;
- 
-		cpu_set(j, covered_cpus);
 	}
 
-	for_each_cpu_mask(j, online_policy_cpus) {
-		freqs.cpu = j;
+	for_each_cpu_mask(i, cmd.mask) {
+		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	}
+	perf->state = next_perf_state;
 
-	if (unlikely(result)) {
-		/*
-		 * We have failed halfway through the frequency change.
-		 * We have sent callbacks to online_policy_cpus and
-		 * acpi_processor_set_performance() has been called on 
-		 * coverd_cpus. Best effort undo..
-		 */
-
-		if (!cpus_empty(covered_cpus)) {
-			for_each_cpu_mask(j, covered_cpus) {
-				policy->cpu = j;
-				acpi_processor_set_performance (data, 
-						j, 
-						cur_state);
-			}
-		}
-
-		tmp = freqs.new;
-		freqs.new = freqs.old;
-		freqs.old = tmp;
-		for_each_cpu_mask(j, online_policy_cpus) {
-			freqs.cpu = j;
-			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-		}
-	}
-
-	set_cpus_allowed(current, saved_mask);
-	return (result);
+	return result;
 }
 
-
-static int
-acpi_cpufreq_verify (
-	struct cpufreq_policy   *policy)
+static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
 {
-	unsigned int result = 0;
-	struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+	struct acpi_cpufreq_data *data = drv_data[policy->cpu];
 
 	dprintk("acpi_cpufreq_verify\n");
 
-	result = cpufreq_frequency_table_verify(policy, 
-			data->freq_table);
-
-	return (result);
+	return cpufreq_frequency_table_verify(policy, data->freq_table);
 }
 
-
 static unsigned long
-acpi_cpufreq_guess_freq (
-	struct cpufreq_acpi_io	*data,
-	unsigned int		cpu)
+acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
 {
-	struct acpi_processor_performance	*perf = data->acpi_data;
+	struct acpi_processor_performance *perf = data->acpi_data;
 
 	if (cpu_khz) {
 		/* search the closest match to cpu_khz */
@@ -338,16 +502,16 @@
 		unsigned long freq;
 		unsigned long freqn = perf->states[0].core_frequency * 1000;
 
-		for (i = 0; i < (perf->state_count - 1); i++) {
+		for (i=0; i<(perf->state_count-1); i++) {
 			freq = freqn;
 			freqn = perf->states[i+1].core_frequency * 1000;
 			if ((2 * cpu_khz) > (freqn + freq)) {
 				perf->state = i;
-				return (freq);
+				return freq;
 			}
 		}
-		perf->state = perf->state_count - 1;
-		return (freqn);
+		perf->state = perf->state_count-1;
+		return freqn;
 	} else {
 		/* assume CPU is at P0... */
 		perf->state = 0;
@@ -355,7 +519,6 @@
 	}
 }
 
-
 /*
  * acpi_cpufreq_early_init - initialize ACPI P-States library
  *
@@ -364,30 +527,34 @@
  * do _PDC and _PSD and find out the processor dependency for the
  * actual init that will happen later...
  */
-static int acpi_cpufreq_early_init_acpi(void)
+static int acpi_cpufreq_early_init(void)
 {
-	struct acpi_processor_performance	*data;
-	unsigned int				i, j;
+	struct acpi_processor_performance *data;
+	cpumask_t covered;
+	unsigned int i, j;
 
 	dprintk("acpi_cpufreq_early_init\n");
 
 	for_each_possible_cpu(i) {
-		data = kzalloc(sizeof(struct acpi_processor_performance), 
-			GFP_KERNEL);
+		data = kzalloc(sizeof(struct acpi_processor_performance),
+			       GFP_KERNEL);
 		if (!data) {
-			for_each_possible_cpu(j) {
+			for_each_cpu_mask(j, covered) {
 				kfree(acpi_perf_data[j]);
 				acpi_perf_data[j] = NULL;
 			}
-			return (-ENOMEM);
+			return -ENOMEM;
 		}
 		acpi_perf_data[i] = data;
+		cpu_set(i, covered);
 	}
 
 	/* Do initialization in ACPI core */
-	return acpi_processor_preregister_performance(acpi_perf_data);
+	acpi_processor_preregister_performance(acpi_perf_data);
+	return 0;
 }
 
+#ifdef CONFIG_SMP
 /*
  * Some BIOSes do SW_ANY coordination internally, either set it up in hw
  * or do it in BIOS firmware and won't inform about it to OS. If not
@@ -414,39 +581,42 @@
 	},
 	{ }
 };
+#endif
 
-static int
-acpi_cpufreq_cpu_init (
-	struct cpufreq_policy   *policy)
+static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-	unsigned int		i;
-	unsigned int		cpu = policy->cpu;
-	struct cpufreq_acpi_io	*data;
-	unsigned int		result = 0;
+	unsigned int i;
+	unsigned int valid_states = 0;
+	unsigned int cpu = policy->cpu;
+	struct acpi_cpufreq_data *data;
+	unsigned int result = 0;
 	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
-	struct acpi_processor_performance	*perf;
+	struct acpi_processor_performance *perf;
 
 	dprintk("acpi_cpufreq_cpu_init\n");
 
 	if (!acpi_perf_data[cpu])
-		return (-ENODEV);
+		return -ENODEV;
 
-	data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
+	data = kzalloc(sizeof(struct acpi_cpufreq_data), GFP_KERNEL);
 	if (!data)
-		return (-ENOMEM);
+		return -ENOMEM;
 
 	data->acpi_data = acpi_perf_data[cpu];
-	acpi_io_data[cpu] = data;
+	drv_data[cpu] = data;
+
+	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))
+		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
 
 	result = acpi_processor_register_performance(data->acpi_data, cpu);
-
 	if (result)
 		goto err_free;
 
 	perf = data->acpi_data;
 	policy->shared_type = perf->shared_type;
+
 	/*
-	 * Will let policy->cpus know about dependency only when software 
+	 * Will let policy->cpus know about dependency only when software
 	 * coordination is required.
 	 */
 	if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
@@ -462,10 +632,6 @@
 	}
 #endif
 
-	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
-		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
-	}
-
 	/* capability check */
 	if (perf->state_count <= 1) {
 		dprintk("No P-States\n");
@@ -473,17 +639,33 @@
 		goto err_unreg;
 	}
 
-	if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
-	    (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
-		dprintk("Unsupported address space [%d, %d]\n",
-			(u32) (perf->control_register.space_id),
-			(u32) (perf->status_register.space_id));
+	if (perf->control_register.space_id != perf->status_register.space_id) {
 		result = -ENODEV;
 		goto err_unreg;
 	}
 
-	/* alloc freq_table */
-	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL);
+	switch (perf->control_register.space_id) {
+	case ACPI_ADR_SPACE_SYSTEM_IO:
+		dprintk("SYSTEM IO addr space\n");
+		data->cpu_feature = SYSTEM_IO_CAPABLE;
+		break;
+	case ACPI_ADR_SPACE_FIXED_HARDWARE:
+		dprintk("HARDWARE addr space\n");
+		if (!check_est_cpu(cpu)) {
+			result = -ENODEV;
+			goto err_unreg;
+		}
+		data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
+		break;
+	default:
+		dprintk("Unknown addr space %d\n",
+			(u32) (perf->control_register.space_id));
+		result = -ENODEV;
+		goto err_unreg;
+	}
+
+	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+		    (perf->state_count+1), GFP_KERNEL);
 	if (!data->freq_table) {
 		result = -ENOMEM;
 		goto err_unreg;
@@ -492,129 +674,140 @@
 	/* detect transition latency */
 	policy->cpuinfo.transition_latency = 0;
 	for (i=0; i<perf->state_count; i++) {
-		if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
-			policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
+		if ((perf->states[i].transition_latency * 1000) >
+		    policy->cpuinfo.transition_latency)
+			policy->cpuinfo.transition_latency =
+			    perf->states[i].transition_latency * 1000;
 	}
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
-	/* The current speed is unknown and not detectable by ACPI...  */
-	policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
-
+	data->max_freq = perf->states[0].core_frequency * 1000;
 	/* table init */
-	for (i=0; i<=perf->state_count; i++)
-	{
-		data->freq_table[i].index = i;
-		if (i<perf->state_count)
-			data->freq_table[i].frequency = perf->states[i].core_frequency * 1000;
-		else
-			data->freq_table[i].frequency = CPUFREQ_TABLE_END;
+	for (i=0; i<perf->state_count; i++) {
+		if (i>0 && perf->states[i].core_frequency ==
+		    perf->states[i-1].core_frequency)
+			continue;
+
+		data->freq_table[valid_states].index = i;
+		data->freq_table[valid_states].frequency =
+		    perf->states[i].core_frequency * 1000;
+		valid_states++;
 	}
+	data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
 
 	result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
-	if (result) {
+	if (result)
 		goto err_freqfree;
+
+	switch (data->cpu_feature) {
+	case ACPI_ADR_SPACE_SYSTEM_IO:
+		/* Current speed is unknown and not detectable by IO port */
+		policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
+		break;
+	case ACPI_ADR_SPACE_FIXED_HARDWARE:
+		acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
+		get_cur_freq_on_cpu(cpu);
+		break;
+	default:
+		break;
 	}
 
 	/* notify BIOS that we exist */
 	acpi_processor_notify_smm(THIS_MODULE);
 
-	printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
-	       cpu);
+	/* Check for APERF/MPERF support in hardware */
+	if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) {
+		unsigned int ecx;
+		ecx = cpuid_ecx(6);
+		if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY)
+			acpi_cpufreq_driver.getavg = get_measured_perf;
+	}
+
+	dprintk("CPU%u - ACPI performance management activated.\n", cpu);
 	for (i = 0; i < perf->state_count; i++)
 		dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
-			(i == perf->state?'*':' '), i,
+			(i == perf->state ? '*' : ' '), i,
 			(u32) perf->states[i].core_frequency,
 			(u32) perf->states[i].power,
 			(u32) perf->states[i].transition_latency);
 
 	cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-	
+
 	/*
 	 * the first call to ->target() should result in us actually
 	 * writing something to the appropriate registers.
 	 */
 	data->resume = 1;
-	
-	return (result);
 
- err_freqfree:
+	return result;
+
+err_freqfree:
 	kfree(data->freq_table);
- err_unreg:
+err_unreg:
 	acpi_processor_unregister_performance(perf, cpu);
- err_free:
+err_free:
 	kfree(data);
-	acpi_io_data[cpu] = NULL;
+	drv_data[cpu] = NULL;
 
-	return (result);
+	return result;
 }
 
-
-static int
-acpi_cpufreq_cpu_exit (
-	struct cpufreq_policy   *policy)
+static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
-	struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
+	struct acpi_cpufreq_data *data = drv_data[policy->cpu];
 
 	dprintk("acpi_cpufreq_cpu_exit\n");
 
 	if (data) {
 		cpufreq_frequency_table_put_attr(policy->cpu);
-		acpi_io_data[policy->cpu] = NULL;
-		acpi_processor_unregister_performance(data->acpi_data, policy->cpu);
+		drv_data[policy->cpu] = NULL;
+		acpi_processor_unregister_performance(data->acpi_data,
+						      policy->cpu);
 		kfree(data);
 	}
 
-	return (0);
+	return 0;
 }
 
-static int
-acpi_cpufreq_resume (
-	struct cpufreq_policy   *policy)
+static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
 {
-	struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
+	struct acpi_cpufreq_data *data = drv_data[policy->cpu];
 
 	dprintk("acpi_cpufreq_resume\n");
 
 	data->resume = 1;
 
-	return (0);
+	return 0;
 }
 
-
-static struct freq_attr* acpi_cpufreq_attr[] = {
+static struct freq_attr *acpi_cpufreq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
-	.verify	= acpi_cpufreq_verify,
-	.target	= acpi_cpufreq_target,
-	.init	= acpi_cpufreq_cpu_init,
-	.exit	= acpi_cpufreq_cpu_exit,
-	.resume	= acpi_cpufreq_resume,
-	.name	= "acpi-cpufreq",
-	.owner	= THIS_MODULE,
-	.attr	= acpi_cpufreq_attr,
+	.verify = acpi_cpufreq_verify,
+	.target = acpi_cpufreq_target,
+	.init = acpi_cpufreq_cpu_init,
+	.exit = acpi_cpufreq_cpu_exit,
+	.resume = acpi_cpufreq_resume,
+	.name = "acpi-cpufreq",
+	.owner = THIS_MODULE,
+	.attr = acpi_cpufreq_attr,
 };
 
-
-static int __init
-acpi_cpufreq_init (void)
+static int __init acpi_cpufreq_init(void)
 {
 	dprintk("acpi_cpufreq_init\n");
 
-	acpi_cpufreq_early_init_acpi();
+	acpi_cpufreq_early_init();
 
 	return cpufreq_register_driver(&acpi_cpufreq_driver);
 }
 
-
-static void __exit
-acpi_cpufreq_exit (void)
+static void __exit acpi_cpufreq_exit(void)
 {
-	unsigned int	i;
+	unsigned int i;
 	dprintk("acpi_cpufreq_exit\n");
 
 	cpufreq_unregister_driver(&acpi_cpufreq_driver);
@@ -627,7 +820,9 @@
 }
 
 module_param(acpi_pstate_strict, uint, 0644);
-MODULE_PARM_DESC(acpi_pstate_strict, "value 0 or non-zero. non-zero -> strict ACPI checks are performed during frequency changes.");
+MODULE_PARM_DESC(acpi_pstate_strict,
+	"value 0 or non-zero. non-zero -> strict ACPI checks are "
+	"performed during frequency changes.");
 
 late_initcall(acpi_cpufreq_init);
 module_exit(acpi_cpufreq_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
index 92afa3b..6667e9c 100644
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -447,7 +447,6 @@
 	int ret;
 	struct gxfreq_params *params;
 	struct pci_dev *gx_pci;
-	u32 class_rev;
 
 	/* Test if we have the right hardware */
 	if ((gx_pci = gx_detect_chipset()) == NULL)
@@ -472,8 +471,7 @@
 	pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
 	pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
 	pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
-        pci_read_config_dword(params->cs55x0, PCI_CLASS_REVISION, &class_rev);
-	params->pci_rev = class_rev && 0xff;
+	pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, &params->pci_rev);
 
 	if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
 		kfree(params);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 7233abe..c548daa 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -410,7 +410,7 @@
 			maxmult=longhaul_get_cpu_mult();
 
 			/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
-			if ((cpu_khz/1000) > 1200)
+			if ((cpu_khz/maxmult) > 13400)
 				fsb = 200;
 			else
 				fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
@@ -583,6 +583,10 @@
 	if (dev == NULL) {
 		reg = 0x76;
 		dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_862X_0, NULL);
+		/* Find CN400 V-Link host bridge */
+		if (dev == NULL)
+			dev = pci_find_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
+
 	}
 	if (dev != NULL) {
 		/* Enable access to port 0x22 */
@@ -734,7 +738,7 @@
 	return 0;
 
 err_acpi:
-	printk(KERN_ERR PFX "No ACPI support. No VT8601 or VT8623 northbridge. Aborting.\n");
+	printk(KERN_ERR PFX "No ACPI support. Unsupported northbridge. Aborting.\n");
 	return -ENODEV;
 }
 
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index 304d2ea..bec5017 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -163,29 +163,27 @@
 
 static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
 {
-	if ((c->x86 == 0x06) && (c->x86_model == 0x09)) {
-		/* Pentium M (Banias) */
-		printk(KERN_WARNING PFX "Warning: Pentium M detected. "
-		       "The speedstep_centrino module offers voltage scaling"
-		       " in addition of frequency scaling. You should use "
-		       "that instead of p4-clockmod, if possible.\n");
-		return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
-	}
-
-	if ((c->x86 == 0x06) && (c->x86_model == 0x0D)) {
-		/* Pentium M (Dothan) */
-		printk(KERN_WARNING PFX "Warning: Pentium M detected. "
-		       "The speedstep_centrino module offers voltage scaling"
-		       " in addition of frequency scaling. You should use "
-		       "that instead of p4-clockmod, if possible.\n");
-		/* on P-4s, the TSC runs with constant frequency independent whether
-		 * throttling is active or not. */
-		p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
-		return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
+	if (c->x86 == 0x06) {
+		if (cpu_has(c, X86_FEATURE_EST))
+			printk(KERN_WARNING PFX "Warning: EST-capable CPU detected. "
+			       "The acpi-cpufreq module offers voltage scaling"
+			       " in addition of frequency scaling. You should use "
+			       "that instead of p4-clockmod, if possible.\n");
+		switch (c->x86_model) {
+		case 0x0E: /* Core */
+		case 0x0F: /* Core Duo */
+			p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
+			return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
+		case 0x0D: /* Pentium M (Dothan) */
+			p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
+			/* fall through */
+		case 0x09: /* Pentium M (Banias) */
+			return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
+		}
 	}
 
 	if (c->x86 != 0xF) {
-		printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <linux@brodo.de>\n");
+		printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <cpufreq@lists.linux.org.uk>\n");
 		return 0;
 	}
 
diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
index ef457d5..b8fb4b5 100644
--- a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
+++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
@@ -153,6 +153,7 @@
 static int __init sc520_freq_init(void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
+	int err;
 
 	/* Test if we have the right hardware */
 	if(c->x86_vendor != X86_VENDOR_AMD ||
@@ -166,7 +167,11 @@
 		return -ENOMEM;
 	}
 
-	return cpufreq_register_driver(&sc520_freq_driver);
+	err = cpufreq_register_driver(&sc520_freq_driver);
+	if (err)
+		iounmap(cpuctl);
+
+	return err;
 }
 
 
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index e8993ba..5113e92 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -36,6 +36,7 @@
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
 
+#define INTEL_MSR_RANGE	(0xffff)
 
 struct cpu_id
 {
@@ -379,6 +380,7 @@
 }
 
 
+#ifdef CONFIG_SMP
 /*
  * Some BIOSes do SW_ANY coordination internally, either set it up in hw
  * or do it in BIOS firmware and won't inform about it to OS. If not
@@ -392,7 +394,6 @@
 	return 0;
 }
 
-
 static struct dmi_system_id sw_any_bug_dmi_table[] = {
 	{
 		.callback = sw_any_bug_found,
@@ -405,7 +406,7 @@
 	},
 	{ }
 };
-
+#endif
 
 /*
  * centrino_cpu_init_acpi - register with ACPI P-States library
@@ -463,8 +464,9 @@
 	}
 
 	for (i=0; i<p->state_count; i++) {
-		if (p->states[i].control != p->states[i].status) {
-			dprintk("Different control (%llu) and status values (%llu)\n",
+		if ((p->states[i].control & INTEL_MSR_RANGE) !=
+		    (p->states[i].status & INTEL_MSR_RANGE)) {
+			dprintk("Different MSR bits in control (%llu) and status (%llu)\n",
 				p->states[i].control, p->states[i].status);
 			result = -EINVAL;
 			goto err_unreg;
@@ -500,7 +502,7 @@
         }
 
         for (i=0; i<p->state_count; i++) {
-		centrino_model[cpu]->op_points[i].index = p->states[i].control;
+		centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE;
 		centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
 		dprintk("adding state %i with frequency %u and control value %04x\n", 
 			i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
@@ -531,6 +533,9 @@
 
 	/* notify BIOS that we exist */
 	acpi_processor_notify_smm(THIS_MODULE);
+	printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI"
+			"config is deprecated.\n "
+			"Use X86_ACPI_CPUFREQ (acpi-cpufreq instead.\n" );
 
 	return 0;
 
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index 4f46cac..d59277c 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -123,6 +123,36 @@
 	return (msr_tmp * 100 * 1000);
 }
 
+static unsigned int pentium_core_get_frequency(void)
+{
+	u32 fsb = 0;
+	u32 msr_lo, msr_tmp;
+
+	rdmsr(MSR_FSB_FREQ, msr_lo, msr_tmp);
+	/* see table B-2 of 25366920.pdf */
+	switch (msr_lo & 0x07) {
+	case 5:
+		fsb = 100000;
+		break;
+	case 1:
+		fsb = 133333;
+		break;
+	case 3:
+		fsb = 166667;
+		break;
+	default:
+		printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
+	}
+
+	rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
+	dprintk("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
+
+	msr_tmp = (msr_lo >> 22) & 0x1f;
+	dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * fsb));
+
+	return (msr_tmp * fsb);
+}
+
 
 static unsigned int pentium4_get_frequency(void)
 {
@@ -174,6 +204,8 @@
 unsigned int speedstep_get_processor_frequency(unsigned int processor)
 {
 	switch (processor) {
+	case SPEEDSTEP_PROCESSOR_PCORE:
+		return pentium_core_get_frequency();
 	case SPEEDSTEP_PROCESSOR_PM:
 		return pentiumM_get_frequency();
 	case SPEEDSTEP_PROCESSOR_P4D:
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
index b735429..b11bcc6 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
@@ -22,6 +22,7 @@
  * the speedstep_get_processor_frequency() call. */
 #define SPEEDSTEP_PROCESSOR_PM			0xFFFFFF03  /* Pentium M  */
 #define SPEEDSTEP_PROCESSOR_P4D			0xFFFFFF04  /* desktop P4  */
+#define SPEEDSTEP_PROCESSOR_PCORE		0xFFFFFF05  /* Core */
 
 /* speedstep states -- only two of them */
 
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index c28333d..ff0d898 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -360,9 +360,6 @@
 	case SPEEDSTEP_PROCESSOR_PIII_C:
 	case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
 		break;
-	case SPEEDSTEP_PROCESSOR_P4M:
-		printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n");
-		break;
 	default:
 		speedstep_processor = 0;
 	}
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 1f9300f..96e9410 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -644,7 +644,85 @@
 #
 # 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_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 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=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+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
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 621037d..060563a 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -23,6 +23,8 @@
 void (*_machine_halt)(void);
 void (*pm_power_off)(void);
 
+EXPORT_SYMBOL(pm_power_off);
+
 void machine_restart(char *command)
 {
 	if (_machine_restart)
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 79f0317..cecff24 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -112,6 +112,7 @@
     /* .exit.text is discarded at runtime, not link time, to deal with
      references from .rodata */
   .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
   . = ALIGN(_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
@@ -139,7 +140,6 @@
 
   /* Sections to be discarded */
   /DISCARD/ : {
-        *(.exit.data)
         *(.exitcall.exit)
 
 	/* ABI crap starts here */
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
index 1720f2c..0677104 100644
--- a/arch/mips/lib/csum_partial_copy.c
+++ b/arch/mips/lib/csum_partial_copy.c
@@ -7,6 +7,7 @@
  * Copyright (C) 1998, 1999 Ralf Baechle
  */
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/string.h>
@@ -29,6 +30,8 @@
 	return sum;
 }
 
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
 /*
  * Copy from userspace and compute checksum.  If we catch an exception
  * then zero the rest of the buffer.
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 77ee5c6..b662c75 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,5 +19,5 @@
 # under Linux.
 #
 
-obj-y := malta_int.o malta_setup.o
+obj-y := malta_int.o malta_mtd.o malta_setup.o
 obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 282f3e5..56ea766 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -21,13 +21,6 @@
 #include <linux/pci.h>
 #include <linux/screen_info.h>
 
-#ifdef CONFIG_MTD
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#endif
-
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
@@ -58,30 +51,6 @@
 	{ .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY },
 };
 
-#ifdef CONFIG_MTD
-static struct mtd_partition malta_mtd_partitions[] = {
-	{
-		.name =		"YAMON",
-		.offset =	0x0,
-		.size =		0x100000,
-		.mask_flags =	MTD_WRITEABLE
-	},
-	{
-		.name =		"User FS",
-		.offset = 	0x100000,
-		.size =		0x2e0000
-	},
-	{
-		.name =		"Board Config",
-		.offset =	0x3e0000,
-		.size =		0x020000,
-		.mask_flags =	MTD_WRITEABLE
-	}
-};
-
-#define number_partitions	(sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition))
-#endif
-
 const char *get_system_type(void)
 {
 	return "MIPS Malta";
@@ -211,14 +180,6 @@
 #endif
 #endif
 
-#ifdef CONFIG_MTD
-	/*
-	 * Support for MTD on Malta. Use the generic physmap driver
-	 */
-	physmap_configure(0x1e000000, 0x400000, 4, NULL);
-	physmap_set_partitions(malta_mtd_partitions, number_partitions);
-#endif
-
 	mips_reboot_setup();
 
 	board_time_init = mips_time_init;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index caf807d..1f954a2 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -32,6 +32,7 @@
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
 
+EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
 EXPORT_SYMBOL(flush_data_cache_page);
 
 #ifdef CONFIG_DMA_NONCOHERENT
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 9e29ba9..ea2d153 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -316,7 +316,7 @@
 void __init paging_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-	unsigned long max_dma, high, low;
+	unsigned long max_dma, low;
 #ifndef CONFIG_FLATMEM
 	unsigned long zholes_size[MAX_NR_ZONES] = { 0, };
 	unsigned long i, j, pfn;
@@ -331,7 +331,6 @@
 
 	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	low = max_low_pfn;
-	high = highend_pfn;
 
 #ifdef CONFIG_ISA
 	if (low < max_dma)
@@ -344,13 +343,13 @@
 	zones_size[ZONE_DMA] = low;
 #endif
 #ifdef CONFIG_HIGHMEM
-	if (cpu_has_dc_aliases) {
-		printk(KERN_WARNING "This processor doesn't support highmem.");
-		if (high - low)
-			printk(" %ldk highmem ignored", high - low);
-		printk("\n");
-	} else
-		zones_size[ZONE_HIGHMEM] = high - low;
+	zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn;
+
+	if (cpu_has_dc_aliases && zones_size[ZONE_HIGHMEM]) {
+		printk(KERN_WARNING "This processor doesn't support highmem."
+		       " %ldk highmem ignored\n", zones_size[ZONE_HIGHMEM]);
+		zones_size[ZONE_HIGHMEM] = 0;
+	}
 #endif
 
 #ifdef CONFIG_FLATMEM
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 56c3c40..8699dad 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -107,6 +107,11 @@
 	bool
 	default y
 
+config GENERIC_BUG
+	bool
+	default y
+	depends on BUG
+
 config DEFAULT_UIMAGE
 	bool
 	help
@@ -478,6 +483,7 @@
 	select PPC_UDBG_16550
 	select PPC_970_NAP
 	select PPC_NATIVE
+	select PPC_RTAS
 	default n
 	help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -714,7 +720,7 @@
 
 config MATH_EMULATION
 	bool "Math emulation"
-	depends on 4xx || 8xx || E200 || E500
+	depends on 4xx || 8xx || E200 || PPC_83xx || E500
 	---help---
 	  Some PowerPC chips designed for embedded applications do not have
 	  a floating-point unit and therefore do not implement the
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index f2d888e..70ed613 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -157,6 +157,7 @@
 CONFIG_PS3_HTAB_SIZE=20
 CONFIG_PS3_DYNAMIC_DMA=y
 CONFIG_PS3_USE_LPAR_ADDR=y
+CONFIG_PS3_VUART=y
 
 #
 # Kernel options
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 4fe53d0..d2ded19 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -77,6 +77,7 @@
 
 ifeq ($(CONFIG_PPC_ISERIES),y)
 extra-y += lparmap.s
+$(obj)/head_64.o:	$(obj)/lparmap.s
 AFLAGS_head_64.o += -I$(obj)
 endif
 
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 9d1614c..b742013 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -833,7 +833,7 @@
 		.pvr_mask		= 0x7fff0000,
 		.pvr_value		= 0x00840000,
 		.cpu_name		= "e300c2",
-		.cpu_features		= CPU_FTRS_E300,
+		.cpu_features		= CPU_FTRS_E300C2,
 		.cpu_user_features	= PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
@@ -1136,8 +1136,7 @@
 		.pvr_mask		= 0xff000fff,
 		.pvr_value		= 0x53000890,
 		.cpu_name		= "440SPe Rev. A",
-		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
-			CPU_FTR_USE_TB,
+		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index d88e182..9417cf5 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -437,6 +437,13 @@
 /* Floating-point unavailable */
 	. = 0x800
 FPUnavailable:
+BEGIN_FTR_SECTION
+/*
+ * Certain Freescale cores don't have a FPU and treat fp instructions
+ * as a FP Unavailable exception.  Redirect to illegal/emulation handling.
+ */
+	b 	ProgramCheck
+END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
 	EXCEPTION_PROLOG
 	bne	load_up_fpu		/* if from user, just load it up */
 	addi	r3,r1,STACK_FRAME_OVERHEAD
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index e2c3c6a..8339fd6 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -23,6 +23,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/cache.h>
+#include <linux/bug.h>
 
 #include "setup.h"
 
@@ -290,23 +291,11 @@
 		    struct module *me)
 {
 	const Elf_Shdr *sect;
+	int err;
 
-	me->arch.bug_table = NULL;
-	me->arch.num_bugs = 0;
-
-	/* Find the __bug_table section, if present */
-	sect = find_section(hdr, sechdrs, "__bug_table");
-	if (sect != NULL) {
-		me->arch.bug_table = (void *) sect->sh_addr;
-		me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
-	}
-
- 	/*
-	 * Strictly speaking this should have a spinlock to protect against
-	 * traversals, but since we only traverse on BUG()s, a spinlock
-	 * could potentially lead to deadlock and thus be counter-productive.
-	 */
-	list_add(&me->arch.bug_list, &module_bug_list);
+	err = module_bug_finalize(hdr, sechdrs, me);
+	if (err)		/* never true, currently */
+		return err;
 
 	/* Apply feature fixups */
 	sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -320,7 +309,7 @@
 
 void module_arch_cleanup(struct module *mod)
 {
-	list_del(&mod->arch.bug_list);
+	module_bug_cleanup(mod);
 }
 
 struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 8dd1f0a..75c7c4f 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -20,6 +20,7 @@
 #include <linux/moduleloader.h>
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/bug.h>
 #include <asm/module.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
@@ -439,23 +440,11 @@
 		const Elf_Shdr *sechdrs, struct module *me)
 {
 	const Elf_Shdr *sect;
+	int err;
 
-	me->arch.bug_table = NULL;
-	me->arch.num_bugs = 0;
-
-	/* Find the __bug_table section, if present */
-	sect = find_section(hdr, sechdrs, "__bug_table");
-	if (sect != NULL) {
-		me->arch.bug_table = (void *) sect->sh_addr;
-		me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
-	}
-
-	/*
-	 * Strictly speaking this should have a spinlock to protect against
-	 * traversals, but since we only traverse on BUG()s, a spinlock
-	 * could potentially lead to deadlock and thus be counter-productive.
-	 */
-	list_add(&me->arch.bug_list, &module_bug_list);
+	err = module_bug_finalize(hdr, sechdrs, me);
+	if (err)
+		return err;
 
 	/* Apply feature fixups */
 	sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -475,7 +464,7 @@
 
 void module_arch_cleanup(struct module *mod)
 {
-	list_del(&mod->arch.bug_list);
+	module_bug_cleanup(mod);
 }
 
 struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 8a06724..e921514 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -109,9 +109,7 @@
 	if (rc)
 		return rc;
 
-	device_create_file(&ofdev->dev, &dev_attr_devspec);
-
-	return 0;
+	return device_create_file(&ofdev->dev, &dev_attr_devspec);
 }
 
 void of_device_unregister(struct of_device *ofdev)
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index b3189d0..3002ea3 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -169,7 +169,7 @@
 	char *name = dev->dev.bus_id;
 	const u32 *reg;
 	u64 addr;
-	long magic;
+	int magic;
 
 	/*
 	 * If it's a DCR based device, use 'd' for native DCRs
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 2f54cd8..8336dea 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -736,25 +736,51 @@
 	return NULL;
 }
 
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
+					       unsigned int devfn)
 {
-	const unsigned int *reg;
-	u8* fdata = (u8*)data;
-	
-	reg = get_property(node, "reg", NULL);
-	if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
-		&& ((reg[0] >> 16) & 0xff) == fdata[0])
-		return 1;
-	return 0;
+	struct device_node *np = NULL;
+	const u32 *reg;
+	unsigned int psize;
+
+	while ((np = of_get_next_child(parent, np)) != NULL) {
+		reg = get_property(np, "reg", &psize);
+		if (reg == NULL || psize < 4)
+			continue;
+		if (((reg[0] >> 8) & 0xff) == devfn)
+			return np;
+	}
+	return NULL;
 }
 
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
-{
-	u8 filter_data[2] = {bus, dev_fn};
 
-	return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
+{
+	struct device_node *parent, *np;
+
+	/* Are we a root bus ? */
+	if (bus->self == NULL || bus->parent == NULL) {
+		struct pci_controller *hose = pci_bus_to_hose(bus->number);
+		if (hose == NULL)
+			return NULL;
+		return of_node_get(hose->arch_data);
+	}
+
+	/* not a root bus, we need to get our parent */
+	parent = scan_OF_for_pci_bus(bus->parent);
+	if (parent == NULL)
+		return NULL;
+
+	/* now iterate for children for a match */
+	np = scan_OF_for_pci_dev(parent, bus->self->devfn);
+	of_node_put(parent);
+
+	/* sanity check */
+	if (strcmp(np->type, "pci") != 0)
+		printk(KERN_WARNING "pci: wrong type \"%s\" for bridge %s\n",
+		       np->type, np->full_name);
+
+	return np;
 }
 
 /*
@@ -763,43 +789,25 @@
 struct device_node *
 pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
 {
-	struct pci_controller *hose;
-	struct device_node *node;
-	int busnr;
+	struct device_node *parent, *np;
 
 	if (!have_of)
 		return NULL;
-	
-	/* Lookup the hose */
-	busnr = bus->number;
-	hose = pci_bus_to_hose(busnr);
-	if (!hose)
-		return NULL;
 
-	/* Check it has an OF node associated */
-	node = (struct device_node *) hose->arch_data;
-	if (!node)
+	DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
+	parent = scan_OF_for_pci_bus(bus);
+	if (parent == NULL)
 		return NULL;
+	DBG(" parent is %s\n", parent ? parent->full_name : "<NULL>");
+	np = scan_OF_for_pci_dev(parent, devfn);
+	of_node_put(parent);
+	DBG(" result is %s\n", np ? np->full_name : "<NULL>");
 
-	/* Fixup bus number according to what OF think it is. */
-#ifdef CONFIG_PPC_PMAC
-	/* The G5 need a special case here. Basically, we don't remap all
-	 * busses on it so we don't create the pci-OF-map. However, we do
-	 * remap the AGP bus and so have to deal with it. A future better
-	 * fix has to be done by making the remapping per-host and always
-	 * filling the pci_to_OF map. --BenH
+	/* XXX most callers don't release the returned node
+	 * mostly because ppc64 doesn't increase the refcount,
+	 * we need to fix that.
 	 */
-	if (machine_is(powermac) && busnr >= 0xf0)
-		busnr -= 0xf0;
-	else
-#endif
-	if (pci_to_OF_bus_map)
-		busnr = pci_to_OF_bus_map[busnr];
-	if (busnr == 0xff)
-		return NULL;
-	
-	/* Now, lookup childs of the hose */
-	return scan_OF_childs_for_device(node->child, busnr, devfn);
+	return np;
 }
 EXPORT_SYMBOL(pci_busdev_to_OF_node);
 
@@ -1544,7 +1552,7 @@
 
 
 static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       unsigned long *offset,
+					       resource_size_t *offset,
 					       enum pci_mmap_state mmap_state)
 {
 	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
@@ -1556,7 +1564,9 @@
 
 	/* If memory, add on the PCI bridge address offset */
 	if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
 		*offset += hose->pci_mem_offset;
+#endif
 		res_bit = IORESOURCE_MEM;
 	} else {
 		io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
@@ -1624,9 +1634,6 @@
 	else
 		prot |= _PAGE_GUARDED;
 
-	printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev),
-		(unsigned long long)rp->start, prot);
-
 	return __pgprot(prot);
 }
 
@@ -1695,7 +1702,7 @@
 			enum pci_mmap_state mmap_state,
 			int write_combine)
 {
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
 	struct resource *rp;
 	int ret;
 
@@ -1808,22 +1815,42 @@
 			  resource_size_t *start, resource_size_t *end)
 {
 	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-	unsigned long offset = 0;
+	resource_size_t offset = 0;
 
 	if (hose == NULL)
 		return;
 
 	if (rsrc->flags & IORESOURCE_IO)
-		offset = (void __iomem *)_IO_BASE - hose->io_base_virt
-			+ hose->io_base_phys;
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
-	*start = rsrc->start + offset;
-	*end = rsrc->end + offset;
+	/* We pass a fully fixed up address to userland for MMIO instead of
+	 * a BAR value because X is lame and expects to be able to use that
+	 * to pass to /dev/mem !
+	 *
+	 * That means that we'll have potentially 64 bits values where some
+	 * userland apps only expect 32 (like X itself since it thinks only
+	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+	 * 32 bits CHRPs :-(
+	 *
+	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
+	 * has been fixed (and the fix spread enough), we can re-enable the
+	 * 2 lines below and pass down a BAR value to userland. In that case
+	 * we'll also have to re-enable the matching code in
+	 * __pci_mmap_make_offset().
+	 *
+	 * BenH.
+	 */
+#if 0
+	else if (rsrc->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+#endif
+
+	*start = rsrc->start - offset;
+	*end = rsrc->end - offset;
 }
 
-void __init
-pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
-		  int flags, char *name)
+void __init pci_init_resource(struct resource *res, resource_size_t start,
+			      resource_size_t end, int flags, char *name)
 {
 	res->start = start;
 	res->end = end;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 6fa9a0a..a6b7692 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -682,7 +682,7 @@
  * Returns negative error code on failure, zero on success.
  */
 static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       unsigned long *offset,
+					       resource_size_t *offset,
 					       enum pci_mmap_state mmap_state)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
@@ -694,7 +694,9 @@
 
 	/* If memory, add on the PCI bridge address offset */
 	if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
 		*offset += hose->pci_mem_offset;
+#endif
 		res_bit = IORESOURCE_MEM;
 	} else {
 		io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
@@ -762,9 +764,6 @@
 	else
 		prot |= _PAGE_GUARDED;
 
-	printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
-	       prot);
-
 	return __pgprot(prot);
 }
 
@@ -832,7 +831,7 @@
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			enum pci_mmap_state mmap_state, int write_combine)
 {
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
 	struct resource *rp;
 	int ret;
 
@@ -1333,20 +1332,41 @@
 
 void pci_resource_to_user(const struct pci_dev *dev, int bar,
 			  const struct resource *rsrc,
-			  u64 *start, u64 *end)
+			  resource_size_t *start, resource_size_t *end)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long offset = 0;
+	resource_size_t offset = 0;
 
 	if (hose == NULL)
 		return;
 
 	if (rsrc->flags & IORESOURCE_IO)
-		offset = pci_io_base - (unsigned long)hose->io_base_virt +
-			hose->io_base_phys;
+		offset = (unsigned long)hose->io_base_virt - pci_io_base;
 
-	*start = rsrc->start + offset;
-	*end = rsrc->end + offset;
+	/* We pass a fully fixed up address to userland for MMIO instead of
+	 * a BAR value because X is lame and expects to be able to use that
+	 * to pass to /dev/mem !
+	 *
+	 * That means that we'll have potentially 64 bits values where some
+	 * userland apps only expect 32 (like X itself since it thinks only
+	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+	 * 32 bits CHRPs :-(
+	 *
+	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
+	 * has been fixed (and the fix spread enough), we can re-enable the
+	 * 2 lines below and pass down a BAR value to userland. In that case
+	 * we'll also have to re-enable the matching code in
+	 * __pci_mmap_make_offset().
+	 *
+	 * BenH.
+	 */
+#if 0
+	else if (rsrc->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+#endif
+
+	*start = rsrc->start - offset;
+	*end = rsrc->end - offset;
 }
 
 struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 9179f07..95776b6 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -208,7 +208,7 @@
 extern long *intercept_table;
 EXPORT_SYMBOL(intercept_table);
 #endif /* CONFIG_PPC_STD_MMU_32 */
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_DCR_NATIVE
 EXPORT_SYMBOL(__mtdcr);
 EXPORT_SYMBOL(__mfdcr);
 #endif
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index c18dbe7..1fc732a 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -804,6 +804,56 @@
 	return of_read_ulong(p, s);
 }
 
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Interpret the ibm,dynamic-memory property in the
+ * /ibm,dynamic-reconfiguration-memory node.
+ * This contains a list of memory blocks along with NUMA affinity
+ * information.
+ */
+static int __init early_init_dt_scan_drconf_memory(unsigned long node)
+{
+	cell_t *dm, *ls;
+	unsigned long l, n;
+	unsigned long base, size, lmb_size, flags;
+
+	ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
+	if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
+		return 0;
+	lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
+
+	dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
+	if (dm == NULL || l < sizeof(cell_t))
+		return 0;
+
+	n = *dm++;	/* number of entries */
+	if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))
+		return 0;
+
+	for (; n != 0; --n) {
+		base = dt_mem_next_cell(dt_root_addr_cells, &dm);
+		flags = dm[3];
+		/* skip DRC index, pad, assoc. list index, flags */
+		dm += 4;
+		/* skip this block if the reserved bit is set in flags (0x80)
+		   or if the block is not assigned to this partition (0x8) */
+		if ((flags & 0x80) || !(flags & 0x8))
+			continue;
+		size = lmb_size;
+		if (iommu_is_off) {
+			if (base >= 0x80000000ul)
+				continue;
+			if ((base + size) > 0x80000000ul)
+				size = 0x80000000ul - base;
+		}
+		lmb_add(base, size);
+	}
+	lmb_dump_all();
+	return 0;
+}
+#else
+#define early_init_dt_scan_drconf_memory(node)	0
+#endif /* CONFIG_PPC_PSERIES */
 
 static int __init early_init_dt_scan_memory(unsigned long node,
 					    const char *uname, int depth, void *data)
@@ -812,6 +862,11 @@
 	cell_t *reg, *endp;
 	unsigned long l;
 
+	/* Look for the ibm,dynamic-reconfiguration-memory node */
+	if (depth == 1 &&
+	    strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
+		return early_init_dt_scan_drconf_memory(node);
+
 	/* We are scanning "memory" nodes only */
 	if (type == NULL) {
 		/*
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 46cf326..520ef42f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -679,7 +679,7 @@
 	/* option vector 5: PAPR/OF options */
 	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
-	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
+	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 387ed0d9..76b5d7e 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -303,6 +303,12 @@
 }
 EXPORT_SYMBOL(rtas_token);
 
+int rtas_service_present(const char *service)
+{
+	return rtas_token(service) != RTAS_UNKNOWN_SERVICE;
+}
+EXPORT_SYMBOL(rtas_service_present);
+
 #ifdef CONFIG_RTAS_ERROR_LOGGING
 /*
  * Return the firmware-specified size of the error log buffer
@@ -810,32 +816,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-/* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
-	/* The token is initialized for real in setup_system() */
-	.token = RTAS_UNKNOWN_SERVICE,
-	.nargs = 0,
-	.nret = 1,
-	.rets = &rtas_stop_self_args.args[0],
-};
-
-void rtas_stop_self(void)
-{
-	struct rtas_args *rtas_args = &rtas_stop_self_args;
-
-	local_irq_disable();
-
-	BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE);
-
-	printk("cpu %u (hwid %u) Ready to die...\n",
-	       smp_processor_id(), hard_smp_processor_id());
-	enter_rtas(__pa(rtas_args));
-
-	panic("Alas, I survived.\n");
-}
-#endif
-
 /*
  * Call early during boot, before mem init or bootmem, to retrieve the RTAS
  * informations from the device-tree and allocate the RMO buffer for userland
@@ -880,9 +860,6 @@
 #endif
 	rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
 
-#ifdef CONFIG_HOTPLUG_CPU
-	rtas_stop_self_args.token = rtas_token("stop-self");
-#endif /* CONFIG_HOTPLUG_CPU */
 #ifdef CONFIG_RTAS_ERROR_LOGGING
 	rtas_last_error_token = rtas_token("rtas-last-error");
 #endif
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 63ed265..400ab2b 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -181,6 +181,8 @@
 SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
 SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
 SYSFS_PMCSETUP(purr, SPRN_PURR);
+SYSFS_PMCSETUP(spurr, SPRN_SPURR);
+SYSFS_PMCSETUP(dscr, SPRN_DSCR);
 
 static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0);
 static SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1);
@@ -194,6 +196,8 @@
 static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7);
 static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8);
 static SYSDEV_ATTR(purr, 0600, show_purr, NULL);
+static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
+static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
 
 static void register_cpu_online(unsigned int cpu)
 {
@@ -231,6 +235,12 @@
 
 	if (cpu_has_feature(CPU_FTR_PURR))
 		sysdev_create_file(s, &attr_purr);
+
+	if (cpu_has_feature(CPU_FTR_SPURR))
+		sysdev_create_file(s, &attr_spurr);
+
+	if (cpu_has_feature(CPU_FTR_DSCR))
+		sysdev_create_file(s, &attr_dscr);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -272,6 +282,12 @@
 
 	if (cpu_has_feature(CPU_FTR_PURR))
 		sysdev_remove_file(s, &attr_purr);
+
+	if (cpu_has_feature(CPU_FTR_SPURR))
+		sysdev_remove_file(s, &attr_spurr);
+
+	if (cpu_has_feature(CPU_FTR_DSCR))
+		sysdev_remove_file(s, &attr_dscr);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 0d4e203..535f506 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -32,6 +32,7 @@
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
 #include <linux/backlight.h>
+#include <linux/bug.h>
 
 #include <asm/kdebug.h>
 #include <asm/pgtable.h>
@@ -727,54 +728,9 @@
 	return -EINVAL;
 }
 
-/*
- * Look through the list of trap instructions that are used for BUG(),
- * BUG_ON() and WARN_ON() and see if we hit one.  At this point we know
- * that the exception was caused by a trap instruction of some kind.
- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
- * otherwise.
- */
-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
-
-#ifndef CONFIG_MODULES
-#define module_find_bug(x)	NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
+int is_valid_bugaddr(unsigned long addr)
 {
-	struct bug_entry *bug;
-
-	for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
-		if (bugaddr == bug->bug_addr)
-			return bug;
-	return module_find_bug(bugaddr);
-}
-
-static int check_bug_trap(struct pt_regs *regs)
-{
-	struct bug_entry *bug;
-	unsigned long addr;
-
-	if (regs->msr & MSR_PR)
-		return 0;	/* not in kernel */
-	addr = regs->nip;	/* address of trap instruction */
-	if (addr < PAGE_OFFSET)
-		return 0;
-	bug = find_bug(regs->nip);
-	if (bug == NULL)
-		return 0;
-	if (bug->line & BUG_WARNING_TRAP) {
-		/* this is a WARN_ON rather than BUG/BUG_ON */
-		printk(KERN_ERR "Badness in %s at %s:%ld\n",
-		       bug->function, bug->file,
-		       bug->line & ~BUG_WARNING_TRAP);
-		dump_stack();
-		return 1;
-	}
-	printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-	       bug->function, bug->file, bug->line);
-
-	return 0;
+	return is_kernel_addr(addr);
 }
 
 void __kprobes program_check_exception(struct pt_regs *regs)
@@ -782,6 +738,8 @@
 	unsigned int reason = get_reason(regs);
 	extern int do_mathemu(struct pt_regs *regs);
 
+	/* We can now get here via a FP Unavailable exception if the core
+	 * has no FPU, in that case no reason flags will be set */
 #ifdef CONFIG_MATH_EMULATION
 	/* (reason & REASON_ILLEGAL) would be the obvious thing here,
 	 * but there seems to be a hardware bug on the 405GP (RevD)
@@ -808,7 +766,9 @@
 			return;
 		if (debugger_bpt(regs))
 			return;
-		if (check_bug_trap(regs)) {
+
+		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
+		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
 			regs->nip += 4;
 			return;
 		}
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 04b9867..04b8e71 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -62,11 +62,7 @@
 		__stop___ex_table = .;
 	}
 
-	__bug_table : {
-		__start___bug_table = .;
-		*(__bug_table)
-		__stop___bug_table = .;
-	}
+	BUG_TABLE
 
 /*
  * Init sections discarded at runtime
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 9da01dc..2627909 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -295,6 +295,63 @@
 	return lmb_end_of_DRAM() - start;
 }
 
+/*
+ * Extract NUMA information from the ibm,dynamic-reconfiguration-memory
+ * node.  This assumes n_mem_{addr,size}_cells have been set.
+ */
+static void __init parse_drconf_memory(struct device_node *memory)
+{
+	const unsigned int *lm, *dm, *aa;
+	unsigned int ls, ld, la;
+	unsigned int n, aam, aalen;
+	unsigned long lmb_size, size;
+	int nid, default_nid = 0;
+	unsigned int start, ai, flags;
+
+	lm = get_property(memory, "ibm,lmb-size", &ls);
+	dm = get_property(memory, "ibm,dynamic-memory", &ld);
+	aa = get_property(memory, "ibm,associativity-lookup-arrays", &la);
+	if (!lm || !dm || !aa ||
+	    ls < sizeof(unsigned int) || ld < sizeof(unsigned int) ||
+	    la < 2 * sizeof(unsigned int))
+		return;
+
+	lmb_size = read_n_cells(n_mem_size_cells, &lm);
+	n = *dm++;		/* number of LMBs */
+	aam = *aa++;		/* number of associativity lists */
+	aalen = *aa++;		/* length of each associativity list */
+	if (ld < (n * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int) ||
+	    la < (aam * aalen + 2) * sizeof(unsigned int))
+		return;
+
+	for (; n != 0; --n) {
+		start = read_n_cells(n_mem_addr_cells, &dm);
+		ai = dm[2];
+		flags = dm[3];
+		dm += 4;
+		/* 0x80 == reserved, 0x8 = assigned to us */
+		if ((flags & 0x80) || !(flags & 0x8))
+			continue;
+		nid = default_nid;
+		/* flags & 0x40 means associativity index is invalid */
+		if (min_common_depth > 0 && min_common_depth <= aalen &&
+		    (flags & 0x40) == 0 && ai < aam) {
+			/* this is like of_node_to_nid_single */
+			nid = aa[ai * aalen + min_common_depth - 1];
+			if (nid == 0xffff || nid >= MAX_NUMNODES)
+				nid = default_nid;
+		}
+		node_set_online(nid);
+
+		size = numa_enforce_memory_limit(start, lmb_size);
+		if (!size)
+			continue;
+
+		add_active_range(nid, start >> PAGE_SHIFT,
+				 (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
+	}
+}
+
 static int __init parse_numa_properties(void)
 {
 	struct device_node *cpu = NULL;
@@ -385,6 +442,14 @@
 			goto new_range;
 	}
 
+	/*
+	 * Now do the same thing for each LMB listed in the ibm,dynamic-memory
+	 * property in the ibm,dynamic-reconfiguration-memory node.
+	 */
+	memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (memory)
+		parse_drconf_memory(memory);
+
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index a375c15..eaff71e 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -40,8 +40,6 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
 #include <asm/of_platform.h>
 
 #include <asm/mpc52xx.h>
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index 616a0a3..70e0d96 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -115,6 +115,7 @@
 
 static struct attribute *spu_attributes[] = {
 	&attr_spu_temperature.attr,
+	NULL,
 };
 
 static struct attribute_group spu_attribute_group = {
@@ -135,6 +136,7 @@
 static struct attribute *ppe_attributes[] = {
 	&attr_ppe_temperature0.attr,
 	&attr_ppe_temperature1.attr,
+	NULL,
 };
 
 static struct attribute_group ppe_attribute_group = {
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index 99c6120..d04ae16 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -382,11 +382,14 @@
 	return IRQ_HANDLED;
 }
 
-int __init cbe_init_pm_irq(void)
+static int __init cbe_init_pm_irq(void)
 {
 	unsigned int irq;
 	int rc, node;
 
+	if (!machine_is(cell))
+		return 0;
+
 	for_each_node(node) {
 		irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
 					       (node << IIC_IRQ_NODE_SHIFT));
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 26945c4..725e195 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -147,7 +147,7 @@
 	struct fdtable *fdt = files_fdtable(current->files);
 	int size = 0, fd;
 
-	for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) {
+	for (fd = 0; fd < fdt->max_fds; fd++) {
 		if (FD_ISSET(fd, fdt->open_fds)) {
 			struct file *file = fcheck(fd);
 
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 3a32ded..3f6a69f 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -562,7 +562,7 @@
 	for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
 		if (np->name == NULL)
 			continue;
-		if (strcmp(np->name, "pci") == 0) {
+		if (!strcmp(np->name, "pci") || !strcmp(np->name, "pcie")) {
 			if (add_bridge(np) == 0)
 				of_node_get(np);
 		}
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 094989d..f12d5c6 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -60,6 +60,7 @@
 #include <asm/of_device.h>
 #include <asm/lmb.h>
 #include <asm/mpic.h>
+#include <asm/rtas.h>
 #include <asm/udbg.h>
 
 #include "maple.h"
@@ -166,6 +167,16 @@
 };
 #endif /* CONFIG_SMP */
 
+static void __init maple_use_rtas_reboot_and_halt_if_present(void)
+{
+	if (rtas_service_present("system-reboot") &&
+	    rtas_service_present("power-off")) {
+		ppc_md.restart = rtas_restart;
+		ppc_md.power_off = rtas_power_off;
+		ppc_md.halt = rtas_halt;
+	}
+}
+
 void __init maple_setup_arch(void)
 {
 	/* init to some ~sane value until calibrate_delay() runs */
@@ -181,6 +192,7 @@
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
+	maple_use_rtas_reboot_and_halt_if_present();
 
 	printk(KERN_DEBUG "Using native/NAP idle loop\n");
 }
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 451bfcd..de52ec4 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -40,4 +40,15 @@
 
 	  If you have any doubt, choose the default y.
 
+config PS3_VUART
+	depends on PPC_PS3
+	bool "PS3 Virtual UART support"
+	default y
+	help
+	  Include support for the PS3 Virtual UART.
+
+	  This support is required for several system services
+	  including the System Manager and AV Settings.  In
+	  general, all users will say Y.
+
 endmenu
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 997243a..69590fb 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -10,6 +10,8 @@
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
 
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
+
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
 obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 3c2d63e..da6e536 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -337,6 +337,7 @@
 			printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n",
 			        pdn->eeh_check_count);
 			dump_stack();
+			msleep(5000);
 			
 			/* re-read the slot reset state */
 			if (read_slot_reset_state(pdn, rets) != 0)
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index c2bc990..cbd6b07 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -170,14 +170,19 @@
 static void eeh_report_resume(struct pci_dev *dev, void *userdata)
 {
 	struct pci_driver *driver = dev->driver;
+	struct device_node *dn = pci_device_to_OF_node(dev);
 
 	dev->error_state = pci_channel_io_normal;
 
 	if (!driver)
 		return;
-	if (!driver->err_handler)
-		return;
-	if (!driver->err_handler->resume)
+
+	if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+		PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+		enable_irq(dev->irq);
+	}
+	if (!driver->err_handler ||
+	    !driver->err_handler->resume)
 		return;
 
 	driver->err_handler->resume(dev);
@@ -407,6 +412,8 @@
 
 		if (rc)
 			result = PCI_ERS_RESULT_NEED_RESET;
+		else
+			result = PCI_ERS_RESULT_RECOVERED;
 	}
 
 	/* If any device has a hard failure, then shut off everything. */
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
new file mode 100644
index 0000000..f460b9c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -0,0 +1,275 @@
+/*
+ * pseries CPU Hotplug infrastructure.
+ *
+ * Split out from arch/powerpc/platforms/pseries/setup.c
+ *  arch/powerpc/kernel/rtas.c, and arch/powerpc/platforms/pseries/smp.c
+ *
+ * Peter Bergner, IBM	March 2001.
+ * Copyright (C) 2001 IBM.
+ * Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+ * Plus various changes from other IBM teams...
+ *
+ * Copyright (C) 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 <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/firmware.h>
+#include <asm/machdep.h>
+#include <asm/vdso_datapage.h>
+#include <asm/pSeries_reconfig.h>
+#include "xics.h"
+
+/* This version can't take the spinlock, because it never returns */
+static struct rtas_args rtas_stop_self_args = {
+	.token = RTAS_UNKNOWN_SERVICE,
+	.nargs = 0,
+	.nret = 1,
+	.rets = &rtas_stop_self_args.args[0],
+};
+
+static void rtas_stop_self(void)
+{
+	struct rtas_args *args = &rtas_stop_self_args;
+
+	local_irq_disable();
+
+	BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+
+	printk("cpu %u (hwid %u) Ready to die...\n",
+	       smp_processor_id(), hard_smp_processor_id());
+	enter_rtas(__pa(args));
+
+	panic("Alas, I survived.\n");
+}
+
+static void pseries_mach_cpu_die(void)
+{
+	local_irq_disable();
+	idle_task_exit();
+	xics_teardown_cpu(0);
+	rtas_stop_self();
+	/* Should never get here... */
+	BUG();
+	for(;;);
+}
+
+static int qcss_tok;	/* query-cpu-stopped-state token */
+
+/* Get state of physical CPU.
+ * Return codes:
+ *	0	- The processor is in the RTAS stopped state
+ *	1	- stop-self is in progress
+ *	2	- The processor is not in the RTAS stopped state
+ *	-1	- Hardware Error
+ *	-2	- Hardware Busy, Try again later.
+ */
+static int query_cpu_stopped(unsigned int pcpu)
+{
+	int cpu_status, status;
+
+	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+	if (status != 0) {
+		printk(KERN_ERR
+		       "RTAS query-cpu-stopped-state failed: %i\n", status);
+		return status;
+	}
+
+	return cpu_status;
+}
+
+static int pseries_cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+
+	cpu_clear(cpu, cpu_online_map);
+	vdso_data->processorCount--;
+
+	/*fix boot_cpuid here*/
+	if (cpu == boot_cpuid)
+		boot_cpuid = any_online_cpu(cpu_online_map);
+
+	/* FIXME: abstract this to not be platform specific later on */
+	xics_migrate_irqs_away();
+	return 0;
+}
+
+static void pseries_cpu_die(unsigned int cpu)
+{
+	int tries;
+	int cpu_status;
+	unsigned int pcpu = get_hard_smp_processor_id(cpu);
+
+	for (tries = 0; tries < 25; tries++) {
+		cpu_status = query_cpu_stopped(pcpu);
+		if (cpu_status == 0 || cpu_status == -1)
+			break;
+		msleep(200);
+	}
+	if (cpu_status != 0) {
+		printk("Querying DEAD? cpu %i (%i) shows %i\n",
+		       cpu, pcpu, cpu_status);
+	}
+
+	/* Isolation and deallocation are definatly done by
+	 * drslot_chrp_cpu.  If they were not they would be
+	 * done here.  Change isolate state to Isolate and
+	 * change allocation-state to Unusable.
+	 */
+	paca[cpu].cpu_start = 0;
+}
+
+/*
+ * Update cpu_present_map and paca(s) for a new cpu node.  The wrinkle
+ * here is that a cpu device node may represent up to two logical cpus
+ * in the SMT case.  We must honor the assumption in other code that
+ * the logical ids for sibling SMT threads x and y are adjacent, such
+ * that x^1 == y and y^1 == x.
+ */
+static int pseries_add_processor(struct device_node *np)
+{
+	unsigned int cpu;
+	cpumask_t candidate_map, tmp = CPU_MASK_NONE;
+	int err = -ENOSPC, len, nthreads, i;
+	const u32 *intserv;
+
+	intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+	if (!intserv)
+		return 0;
+
+	nthreads = len / sizeof(u32);
+	for (i = 0; i < nthreads; i++)
+		cpu_set(i, tmp);
+
+	lock_cpu_hotplug();
+
+	BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
+
+	/* Get a bitmap of unoccupied slots. */
+	cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
+	if (cpus_empty(candidate_map)) {
+		/* If we get here, it most likely means that NR_CPUS is
+		 * less than the partition's max processors setting.
+		 */
+		printk(KERN_ERR "Cannot add cpu %s; this system configuration"
+		       " supports %d logical cpus.\n", np->full_name,
+		       cpus_weight(cpu_possible_map));
+		goto out_unlock;
+	}
+
+	while (!cpus_empty(tmp))
+		if (cpus_subset(tmp, candidate_map))
+			/* Found a range where we can insert the new cpu(s) */
+			break;
+		else
+			cpus_shift_left(tmp, tmp, nthreads);
+
+	if (cpus_empty(tmp)) {
+		printk(KERN_ERR "Unable to find space in cpu_present_map for"
+		       " processor %s with %d thread(s)\n", np->name,
+		       nthreads);
+		goto out_unlock;
+	}
+
+	for_each_cpu_mask(cpu, tmp) {
+		BUG_ON(cpu_isset(cpu, cpu_present_map));
+		cpu_set(cpu, cpu_present_map);
+		set_hard_smp_processor_id(cpu, *intserv++);
+	}
+	err = 0;
+out_unlock:
+	unlock_cpu_hotplug();
+	return err;
+}
+
+/*
+ * Update the present map for a cpu node which is going away, and set
+ * the hard id in the paca(s) to -1 to be consistent with boot time
+ * convention for non-present cpus.
+ */
+static void pseries_remove_processor(struct device_node *np)
+{
+	unsigned int cpu;
+	int len, nthreads, i;
+	const u32 *intserv;
+
+	intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+	if (!intserv)
+		return;
+
+	nthreads = len / sizeof(u32);
+
+	lock_cpu_hotplug();
+	for (i = 0; i < nthreads; i++) {
+		for_each_present_cpu(cpu) {
+			if (get_hard_smp_processor_id(cpu) != intserv[i])
+				continue;
+			BUG_ON(cpu_online(cpu));
+			cpu_clear(cpu, cpu_present_map);
+			set_hard_smp_processor_id(cpu, -1);
+			break;
+		}
+		if (cpu == NR_CPUS)
+			printk(KERN_WARNING "Could not find cpu to remove "
+			       "with physical id 0x%x\n", intserv[i]);
+	}
+	unlock_cpu_hotplug();
+}
+
+static int pseries_smp_notifier(struct notifier_block *nb,
+				unsigned long action, void *node)
+{
+	int err = NOTIFY_OK;
+
+	switch (action) {
+	case PSERIES_RECONFIG_ADD:
+		if (pseries_add_processor(node))
+			err = NOTIFY_BAD;
+		break;
+	case PSERIES_RECONFIG_REMOVE:
+		pseries_remove_processor(node);
+		break;
+	default:
+		err = NOTIFY_DONE;
+		break;
+	}
+	return err;
+}
+
+static struct notifier_block pseries_smp_nb = {
+	.notifier_call = pseries_smp_notifier,
+};
+
+static int __init pseries_cpu_hotplug_init(void)
+{
+	rtas_stop_self_args.token = rtas_token("stop-self");
+	qcss_tok = rtas_token("query-cpu-stopped-state");
+
+	if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+			qcss_tok == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_INFO "CPU Hotplug not supported by firmware "
+				"- disabling.\n");
+		return 0;
+	}
+
+	ppc_md.cpu_die = pseries_mach_cpu_die;
+	smp_ops->cpu_disable = pseries_cpu_disable;
+	smp_ops->cpu_die = pseries_cpu_die;
+
+	/* Processors can be added/removed only on LPAR */
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		pSeries_reconfig_notifier_register(&pseries_smp_nb);
+
+	return 0;
+}
+arch_initcall(pseries_cpu_hotplug_init);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 0dc2548..042ecae 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -347,21 +347,6 @@
 }
 arch_initcall(pSeries_init_panel);
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void pSeries_mach_cpu_die(void)
-{
-	local_irq_disable();
-	idle_task_exit();
-	xics_teardown_cpu(0);
-	rtas_stop_self();
-	/* Should never get here... */
-	BUG();
-	for(;;);
-}
-#else
-#define pSeries_mach_cpu_die NULL
-#endif
-
 static int pseries_set_dabr(unsigned long dabr)
 {
 	return plpar_hcall_norets(H_SET_DABR, dabr);
@@ -437,19 +422,14 @@
 	if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
  		powerpc_firmware_features |= FW_FEATURE_LPAR;
 
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		hpte_init_lpar();
-	else
-		hpte_init_native();
-
  	return 1;
 }
 
 static int __init pSeries_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
- 	char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
- 					  "device_type", NULL);
+ 	char *dtype = of_get_flat_dt_prop(root, "device_type", NULL);
+
  	if (dtype == NULL)
  		return 0;
  	if (strcmp(dtype, "chrp"))
@@ -467,6 +447,11 @@
 	/* Now try to figure out if we are running on LPAR */
 	of_scan_flat_dt(pSeries_probe_hypertas, NULL);
 
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		hpte_init_lpar();
+	else
+		hpte_init_native();
+
 	DBG("Machine is%s LPAR !\n",
 	    (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
 
@@ -561,7 +546,6 @@
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
-	.cpu_die		= pSeries_mach_cpu_die,
 	.get_boot_time		= rtas_get_boot_time,
 	.get_rtc_time		= rtas_get_rtc_time,
 	.set_rtc_time		= rtas_set_rtc_time,
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index c6624b8..4408518 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -64,197 +64,6 @@
 
 extern void generic_secondary_smp_init(unsigned long);
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-/* Get state of physical CPU.
- * Return codes:
- *	0	- The processor is in the RTAS stopped state
- *	1	- stop-self is in progress
- *	2	- The processor is not in the RTAS stopped state
- *	-1	- Hardware Error
- *	-2	- Hardware Busy, Try again later.
- */
-static int query_cpu_stopped(unsigned int pcpu)
-{
-	int cpu_status;
-	int status, qcss_tok;
-
-	qcss_tok = rtas_token("query-cpu-stopped-state");
-	if (qcss_tok == RTAS_UNKNOWN_SERVICE)
-		return -1;
-	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
-	if (status != 0) {
-		printk(KERN_ERR
-		       "RTAS query-cpu-stopped-state failed: %i\n", status);
-		return status;
-	}
-
-	return cpu_status;
-}
-
-static int pSeries_cpu_disable(void)
-{
-	int cpu = smp_processor_id();
-
-	cpu_clear(cpu, cpu_online_map);
-	vdso_data->processorCount--;
-
-	/*fix boot_cpuid here*/
-	if (cpu == boot_cpuid)
-		boot_cpuid = any_online_cpu(cpu_online_map);
-
-	/* FIXME: abstract this to not be platform specific later on */
-	xics_migrate_irqs_away();
-	return 0;
-}
-
-static void pSeries_cpu_die(unsigned int cpu)
-{
-	int tries;
-	int cpu_status;
-	unsigned int pcpu = get_hard_smp_processor_id(cpu);
-
-	for (tries = 0; tries < 25; tries++) {
-		cpu_status = query_cpu_stopped(pcpu);
-		if (cpu_status == 0 || cpu_status == -1)
-			break;
-		msleep(200);
-	}
-	if (cpu_status != 0) {
-		printk("Querying DEAD? cpu %i (%i) shows %i\n",
-		       cpu, pcpu, cpu_status);
-	}
-
-	/* Isolation and deallocation are definatly done by
-	 * drslot_chrp_cpu.  If they were not they would be
-	 * done here.  Change isolate state to Isolate and
-	 * change allocation-state to Unusable.
-	 */
-	paca[cpu].cpu_start = 0;
-}
-
-/*
- * Update cpu_present_map and paca(s) for a new cpu node.  The wrinkle
- * here is that a cpu device node may represent up to two logical cpus
- * in the SMT case.  We must honor the assumption in other code that
- * the logical ids for sibling SMT threads x and y are adjacent, such
- * that x^1 == y and y^1 == x.
- */
-static int pSeries_add_processor(struct device_node *np)
-{
-	unsigned int cpu;
-	cpumask_t candidate_map, tmp = CPU_MASK_NONE;
-	int err = -ENOSPC, len, nthreads, i;
-	const u32 *intserv;
-
-	intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
-	if (!intserv)
-		return 0;
-
-	nthreads = len / sizeof(u32);
-	for (i = 0; i < nthreads; i++)
-		cpu_set(i, tmp);
-
-	lock_cpu_hotplug();
-
-	BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
-
-	/* Get a bitmap of unoccupied slots. */
-	cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
-	if (cpus_empty(candidate_map)) {
-		/* If we get here, it most likely means that NR_CPUS is
-		 * less than the partition's max processors setting.
-		 */
-		printk(KERN_ERR "Cannot add cpu %s; this system configuration"
-		       " supports %d logical cpus.\n", np->full_name,
-		       cpus_weight(cpu_possible_map));
-		goto out_unlock;
-	}
-
-	while (!cpus_empty(tmp))
-		if (cpus_subset(tmp, candidate_map))
-			/* Found a range where we can insert the new cpu(s) */
-			break;
-		else
-			cpus_shift_left(tmp, tmp, nthreads);
-
-	if (cpus_empty(tmp)) {
-		printk(KERN_ERR "Unable to find space in cpu_present_map for"
-		       " processor %s with %d thread(s)\n", np->name,
-		       nthreads);
-		goto out_unlock;
-	}
-
-	for_each_cpu_mask(cpu, tmp) {
-		BUG_ON(cpu_isset(cpu, cpu_present_map));
-		cpu_set(cpu, cpu_present_map);
-		set_hard_smp_processor_id(cpu, *intserv++);
-	}
-	err = 0;
-out_unlock:
-	unlock_cpu_hotplug();
-	return err;
-}
-
-/*
- * Update the present map for a cpu node which is going away, and set
- * the hard id in the paca(s) to -1 to be consistent with boot time
- * convention for non-present cpus.
- */
-static void pSeries_remove_processor(struct device_node *np)
-{
-	unsigned int cpu;
-	int len, nthreads, i;
-	const u32 *intserv;
-
-	intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
-	if (!intserv)
-		return;
-
-	nthreads = len / sizeof(u32);
-
-	lock_cpu_hotplug();
-	for (i = 0; i < nthreads; i++) {
-		for_each_present_cpu(cpu) {
-			if (get_hard_smp_processor_id(cpu) != intserv[i])
-				continue;
-			BUG_ON(cpu_online(cpu));
-			cpu_clear(cpu, cpu_present_map);
-			set_hard_smp_processor_id(cpu, -1);
-			break;
-		}
-		if (cpu == NR_CPUS)
-			printk(KERN_WARNING "Could not find cpu to remove "
-			       "with physical id 0x%x\n", intserv[i]);
-	}
-	unlock_cpu_hotplug();
-}
-
-static int pSeries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node)
-{
-	int err = NOTIFY_OK;
-
-	switch (action) {
-	case PSERIES_RECONFIG_ADD:
-		if (pSeries_add_processor(node))
-			err = NOTIFY_BAD;
-		break;
-	case PSERIES_RECONFIG_REMOVE:
-		pSeries_remove_processor(node);
-		break;
-	default:
-		err = NOTIFY_DONE;
-		break;
-	}
-	return err;
-}
-
-static struct notifier_block pSeries_smp_nb = {
-	.notifier_call = pSeries_smp_notifier,
-};
-
-#endif /* CONFIG_HOTPLUG_CPU */
-
 /**
  * smp_startup_cpu() - start the given cpu
  *
@@ -422,15 +231,6 @@
 
 	DBG(" -> smp_init_pSeries()\n");
 
-#ifdef CONFIG_HOTPLUG_CPU
-	smp_ops->cpu_disable = pSeries_cpu_disable;
-	smp_ops->cpu_die = pSeries_cpu_die;
-
-	/* Processors can be added/removed only on LPAR */
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		pSeries_reconfig_notifier_register(&pSeries_smp_nb);
-#endif
-
 	/* Mark threads which are still spinning in hold loops. */
 	if (cpu_has_feature(CPU_FTR_SMT)) {
 		for_each_present_cpu(i) { 
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 6cc3459..04d4917 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,7 +5,8 @@
 obj-$(CONFIG_MPIC)		+= mpic.o
 obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)	+= grackle.o
-obj-$(CONFIG_PPC_DCR)		+= dcr.o dcr-low.o
+obj-$(CONFIG_PPC_DCR)		+= dcr.o
+obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.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/dcr.S b/arch/powerpc/sysdev/dcr.S
deleted file mode 100644
index 2078f39..0000000
--- a/arch/powerpc/sysdev/dcr.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * "Indirect" DCR access
- *
- * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.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.
- */
-
-#include <asm/ppc_asm.h>
-#include <asm/processor.h>
-
-#define DCR_ACCESS_PROLOG(table) \
-	rlwinm  r3,r3,4,18,27;   \
-	lis     r5,table@h;      \
-	ori     r5,r5,table@l;   \
-	add     r3,r3,r5;        \
-	mtctr   r3;              \
-	bctr
-
-_GLOBAL(__mfdcr)
-	DCR_ACCESS_PROLOG(__mfdcr_table)
-
-_GLOBAL(__mtdcr)
-	DCR_ACCESS_PROLOG(__mtdcr_table)
-
-__mfdcr_table:
-	mfdcr  r3,0; blr
-__mtdcr_table:
-	mtdcr  0,r4; blr
-
-dcr     = 1
-        .rept   1023
-	mfdcr   r3,dcr; blr
-	mtdcr   dcr,r4; blr
-	dcr     = dcr + 1
-	.endr
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 6995f51..74e48d9 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -223,23 +223,15 @@
 	qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
 		    temp & ~qe_ic_info[src].mask);
 
-	spin_unlock_irqrestore(&qe_ic_lock, flags);
-}
-
-static void qe_ic_mask_irq_and_ack(unsigned int virq)
-{
-	struct qe_ic *qe_ic = qe_ic_from_irq(virq);
-	unsigned int src = virq_to_hw(virq);
-	unsigned long flags;
-	u32 temp;
-
-	spin_lock_irqsave(&qe_ic_lock, flags);
-
-	temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
-	qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
-		    temp & ~qe_ic_info[src].mask);
-
-	/* There is nothing to do for ack here, ack is handled in ISR */
+	/* Flush the above write before enabling interrupts; otherwise,
+	 * spurious interrupts will sometimes happen.  To be 100% sure
+	 * that the write has reached the device before interrupts are
+	 * enabled, the mask register would have to be read back; however,
+	 * this is not required for correctness, only to avoid wasting
+	 * time on a large number of spurious interrupts.  In testing,
+	 * a sync reduced the observed spurious interrupts to zero.
+	 */
+	mb();
 
 	spin_unlock_irqrestore(&qe_ic_lock, flags);
 }
@@ -248,7 +240,7 @@
 	.typename = " QEIC  ",
 	.unmask = qe_ic_unmask_irq,
 	.mask = qe_ic_mask_irq,
-	.mask_ack = qe_ic_mask_irq_and_ack,
+	.mask_ack = qe_ic_mask_irq,
 };
 
 static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
@@ -331,34 +323,22 @@
 	return irq_linear_revmap(qe_ic->irqhost, irq);
 }
 
-/* FIXME: We mask all the QE Low interrupts while handling.  We should
- * let other interrupt come in, but BAD interrupts are generated */
 void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc)
 {
 	struct qe_ic *qe_ic = desc->handler_data;
-	struct irq_chip *chip = irq_desc[irq].chip;
-
 	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
 
-	chip->mask_ack(irq);
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	chip->unmask(irq);
 }
 
-/* FIXME: We mask all the QE High interrupts while handling.  We should
- * let other interrupt come in, but BAD interrupts are generated */
 void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc)
 {
 	struct qe_ic *qe_ic = desc->handler_data;
-	struct irq_chip *chip = irq_desc[irq].chip;
-
 	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
 
-	chip->mask_ack(irq);
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	chip->unmask(irq);
 }
 
 void __init qe_ic_init(struct device_node *node, unsigned int flags)
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c
index bf5b3f1..c855a3b 100644
--- a/arch/powerpc/sysdev/rom.c
+++ b/arch/powerpc/sysdev/rom.c
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <asm/of_device.h>
+#include <asm/of_platform.h>
 
 static int __init powerpc_flash_init(void)
 {
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index a34ed49..77540a2 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -22,6 +22,7 @@
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/bug.h>
 
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -35,7 +36,6 @@
 #include <asm/cputable.h>
 #include <asm/rtas.h>
 #include <asm/sstep.h>
-#include <asm/bug.h>
 #include <asm/irq_regs.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
@@ -1346,7 +1346,7 @@
 
 static void print_bug_trap(struct pt_regs *regs)
 {
-	struct bug_entry *bug;
+	const struct bug_entry *bug;
 	unsigned long addr;
 
 	if (regs->msr & MSR_PR)
@@ -1357,11 +1357,11 @@
 	bug = find_bug(regs->nip);
 	if (bug == NULL)
 		return;
-	if (bug->line & BUG_WARNING_TRAP)
+	if (is_warning_bug(bug))
 		return;
 
-	printf("kernel BUG in %s at %s:%d!\n",
-	       bug->function, bug->file, (unsigned int)bug->line);
+	printf("kernel BUG at %s:%u!\n",
+	       bug->file, bug->line);
 }
 
 void excprint(struct pt_regs *fp)
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 63808e0..5e723c4 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -879,7 +879,7 @@
 
 
 static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       unsigned long *offset,
+					       resource_size_t *offset,
 					       enum pci_mmap_state mmap_state)
 {
 	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
@@ -891,7 +891,9 @@
 
 	/* If memory, add on the PCI bridge address offset */
 	if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
 		*offset += hose->pci_mem_offset;
+#endif
 		res_bit = IORESOURCE_MEM;
 	} else {
 		io_offset = hose->io_base_virt - ___IO_BASE;
@@ -1030,7 +1032,7 @@
 			enum pci_mmap_state mmap_state,
 			int write_combine)
 {
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
 	struct resource *rp;
 	int ret;
 
@@ -1132,21 +1134,42 @@
 			  resource_size_t *start, resource_size_t *end)
 {
 	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-	unsigned long offset = 0;
+	resource_size_t offset = 0;
 
 	if (hose == NULL)
 		return;
 
 	if (rsrc->flags & IORESOURCE_IO)
-		offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
-	*start = rsrc->start + offset;
-	*end = rsrc->end + offset;
+	/* We pass a fully fixed up address to userland for MMIO instead of
+	 * a BAR value because X is lame and expects to be able to use that
+	 * to pass to /dev/mem !
+	 *
+	 * That means that we'll have potentially 64 bits values where some
+	 * userland apps only expect 32 (like X itself since it thinks only
+	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+	 * 32 bits CHRPs :-(
+	 *
+	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
+	 * has been fixed (and the fix spread enough), we can re-enable the
+	 * 2 lines below and pass down a BAR value to userland. In that case
+	 * we'll also have to re-enable the matching code in
+	 * __pci_mmap_make_offset().
+	 *
+	 * BenH.
+	 */
+#if 0
+	else if (rsrc->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+#endif
+
+	*start = rsrc->start - offset;
+	*end = rsrc->end - offset;
 }
 
-void __init
-pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
-		  int flags, char *name)
+void __init pci_init_resource(struct resource *res, resource_size_t start,
+			      resource_size_t end, int flags, char *name)
 {
 	res->start = start;
 	res->end = end;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 8e24c40..3aa3b88 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -479,7 +479,7 @@
 	int "CPU Mode Pin Setting"
 	depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
 	help
-	  MD2 - MD0 Setting.
+	  MD2 - MD0 pin setting.
 
 menu "CPU Frequency scaling"
 
@@ -580,18 +580,6 @@
 
 source "kernel/Kconfig.preempt"
 
-config CPU_HAS_SR_RB
-	bool "CPU has SR.RB"
-	depends on CPU_SH3 || CPU_SH4
-	default y
-	help
-	  This will enable the use of SR.RB register bank usage. Processors
-	  that are lacking this bit must have another method in place for
-	  accomplishing what is taken care of by the banked registers.
-
-	  See <file:Documentation/sh/register-banks.txt> for further
-	  information on SR.RB and register banking in the kernel in general.
-
 config NODES_SHIFT
 	int
 	default "1"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 66a25ef4..87902e0 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -31,7 +31,8 @@
 	hex "SCIF port for early console"
 	depends on EARLY_SCIF_CONSOLE
 	default "0xffe00000" if CPU_SUBTYPE_SH7780
-	default "0xfffe9800" if CPU_SUBTYPE_SH72060
+	default "0xfffe9800" if CPU_SUBTYPE_SH7206
+	default "0xf8420000" if CPU_SUBTYPE_SH7619
 	default "0xffe80000" if CPU_SH4
 
 config EARLY_PRINTK
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index d10bba5..c1dbef2 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -179,7 +179,7 @@
 
 all: zImage
 
-zImage: vmlinux
+zImage uImage uImage.srec vmlinux.srec: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 compressed: zImage
@@ -190,5 +190,8 @@
 CLEAN_FILES += include/asm-sh/machtypes.h
 
 define archhelp
-	@echo '  zImage 	           - Compressed kernel image (arch/sh/boot/zImage)'
+	@echo '* zImage 	           - Compressed kernel image'
+	@echo '  vmlinux.srec	           - Create an ELF S-record'
+	@echo '  uImage  	           - Create a bootable image for U-Boot'
+	@echo '  uImage.srec  	           - Create an S-record for U-Boot'
 endef
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
index 8f2e1c6..3eba6d0 100644
--- a/arch/sh/boards/landisk/irq.c
+++ b/arch/sh/boards/landisk/irq.c
@@ -16,8 +16,8 @@
  */
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <asm/io.h>
-#include <asm/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
 #include <asm/landisk/iodata_landisk.h>
 
 static void enable_landisk_irq(unsigned int irq);
diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c
index 3fb0c5f..27da884 100644
--- a/arch/sh/boards/se/7206/irq.c
+++ b/arch/sh/boards/se/7206/irq.c
@@ -10,6 +10,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <asm/se7206.h>
 
 #define INTSTS0 0x31800000
@@ -18,6 +19,13 @@
 #define INTMSK1 0x31800006
 #define INTSEL  0x31800008
 
+#define IRQ0_IRQ 64
+#define IRQ1_IRQ 65
+#define IRQ3_IRQ 67
+
+#define INTC_IPR01 0xfffe0818
+#define INTC_ICR1  0xfffe0802
+
 static void disable_se7206_irq(unsigned int irq)
 {
 	unsigned short val;
@@ -39,7 +47,7 @@
 	case IRQ1_IRQ:
 		msk0 |= 0x000f;
 		break;
-	case IRQ2_IRQ:
+	case IRQ3_IRQ:
 		msk0 |= 0x0f00;
 		msk1 |= 0x00ff;
 		break;
@@ -70,7 +78,7 @@
 	case IRQ1_IRQ:
 		msk0 &= ~0x000f;
 		break;
-	case IRQ2_IRQ:
+	case IRQ3_IRQ:
 		msk0 &= ~0x0f00;
 		msk1 &= ~0x00ff;
 		break;
@@ -96,7 +104,7 @@
 	case IRQ1_IRQ:
 		sts0 &= ~0x000f;
 		break;
-	case IRQ2_IRQ:
+	case IRQ3_IRQ:
 		sts0 &= ~0x0f00;
 		sts1 &= ~0x00ff;
 		break;
@@ -106,7 +114,7 @@
 }
 
 static struct irq_chip se7206_irq_chip __read_mostly = {
-	.name		= "SE7206-FPGA-IRQ",
+	.name		= "SE7206-FPGA",
 	.mask		= disable_se7206_irq,
 	.unmask		= enable_se7206_irq,
 	.mask_ack	= disable_se7206_irq,
diff --git a/arch/sh/boards/se/7619/Makefile b/arch/sh/boards/se/7619/Makefile
index 3666eca..d21775c 100644
--- a/arch/sh/boards/se/7619/Makefile
+++ b/arch/sh/boards/se/7619/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the 7619 SolutionEngine specific parts of the kernel
 #
 
-obj-y	 := setup.o io.o
+obj-y	 := setup.o
diff --git a/arch/sh/boards/se/7619/io.c b/arch/sh/boards/se/7619/io.c
deleted file mode 100644
index 176f1f39c..0000000
--- a/arch/sh/boards/se/7619/io.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * linux/arch/sh/boards/se/7619/io.c
- *
- * Copyright (C) 2006  Yoshinori Sato
- *
- * I/O routine for Hitachi 7619 SolutionEngine.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <asm/se7619.h>
-#include <asm/irq.h>
-
-/* FIXME: M3A-ZAB7 Compact Flash Slot support */
-
-static inline void delay(void)
-{
-	ctrl_inw(0xa0000000);	/* Uncached ROM area (P2) */
-}
-
-#define badio(name,port) \
-  printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \
-	 #name, (port), (__u32) __builtin_return_address(0))
-
-unsigned char se7619___inb(unsigned long port)
-{
-	badio(inb, port);
-	return 0;
-}
-
-unsigned char se7619___inb_p(unsigned long port)
-{
-	badio(inb_p, port);
-	delay();
-	return 0;
-}
-
-unsigned short se7619___inw(unsigned long port)
-{
-	badio(inw, port);
-	return 0;
-}
-
-unsigned int se7619___inl(unsigned long port)
-{
-	badio(inl, port);
-	return 0;
-}
-
-void se7619___outb(unsigned char value, unsigned long port)
-{
-	badio(outb, port);
-}
-
-void se7619___outb_p(unsigned char value, unsigned long port)
-{
-	badio(outb_p, port);
-	delay();
-}
-
-void se7619___outw(unsigned short value, unsigned long port)
-{
-	badio(outw, port);
-}
-
-void se7619___outl(unsigned int value, unsigned long port)
-{
-	badio(outl, port);
-}
-
-void se7619___insb(unsigned long port, void *addr, unsigned long count)
-{
-	badio(inw, port);
-}
-
-void se7619___insw(unsigned long port, void *addr, unsigned long count)
-{
-	badio(inw, port);
-}
-
-void se7619___insl(unsigned long port, void *addr, unsigned long count)
-{
-	badio(insl, port);
-}
-
-void se7619___outsb(unsigned long port, const void *addr, unsigned long count)
-{
-	badio(insl, port);
-}
-
-void se7619___outsw(unsigned long port, const void *addr, unsigned long count)
-{
-	badio(insl, port);
-}
-
-void se7619___outsl(unsigned long port, const void *addr, unsigned long count)
-{
-	badio(outsw, port);
-}
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
index e627b26..52d2c4d 100644
--- a/arch/sh/boards/se/7619/setup.c
+++ b/arch/sh/boards/se/7619/setup.c
@@ -9,7 +9,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <asm/io.h>
-#include <asm/se7619.h>
 #include <asm/machvec.h>
 
 /*
@@ -19,25 +18,5 @@
 struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 108,
-	.mv_inb			= se7619___inb,
-	.mv_inw			= se7619___inw,
-	.mv_inl			= se7619___inl,
-	.mv_outb		= se7619___outb,
-	.mv_outw		= se7619___outw,
-	.mv_outl		= se7619___outl,
-
-	.mv_inb_p		= se7619___inb_p,
-	.mv_inw_p		= se7619___inw,
-	.mv_inl_p		= se7619___inl,
-	.mv_outb_p		= se7619___outb_p,
-	.mv_outw_p		= se7619___outw,
-	.mv_outl_p		= se7619___outl,
-
-	.mv_insb		= se7619___insb,
-	.mv_insw		= se7619___insw,
-	.mv_insl		= se7619___insl,
-	.mv_outsb		= se7619___outsb,
-	.mv_outsw		= se7619___outsw,
-	.mv_outsl		= se7619___outsl,
 };
 ALIAS_MV(se)
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index 60797b3..11dc272c 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -8,13 +8,49 @@
 # Copyright (C) 1999 Stuart Menefy
 #
 
-targets := zImage
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+#
+# Assign safe dummy values if these variables are not defined,
+# in order to suppress error message.
+#
+CONFIG_PAGE_OFFSET	?= 0x80000000
+CONFIG_MEMORY_START	?= 0x0c000000
+CONFIG_BOOT_LINK_OFFSET	?= 0x00800000
+CONFIG_ZERO_PAGE_OFFSET	?= 0x00001000
+
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+       CONFIG_ZERO_PAGE_OFFSET
+
+targets := zImage vmlinux.srec uImage uImage.srec
 subdir- := compressed
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
-	@echo 'Kernel: $@ is ready'
+	@echo '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
+KERNEL_LOAD	:= $(shell printf "0x%8x" $$[$(CONFIG_PAGE_OFFSET)  + \
+					     $(CONFIG_MEMORY_START) + \
+					     $(CONFIG_ZERO_PAGE_OFFSET)+0x1000])
+
+quiet_cmd_uimage = UIMAGE  $@
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
+		   -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \
+		   -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
+$(obj)/uImage: $(obj)/zImage FORCE
+	$(call if_changed,uimage)
+	@echo '  Image $@ is ready'
+
+OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
+$(obj)/vmlinux.srec: $(obj)/compressed/vmlinux
+	$(call if_changed,objcopy)
+
+OBJCOPYFLAGS_uImage.srec := -I binary -O srec
+$(obj)/uImage.srec: $(obj)/uImage
+	$(call if_changed,objcopy)
+
+clean-files	+= uImage uImage.srec vmlinux.srec
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index e5f4437..d951241 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -15,13 +15,7 @@
 
 #
 # IMAGE_OFFSET is the load offset of the compression loader
-# Assign dummy values if these 2 variables are not defined,
-# in order to suppress error message.
 #
-CONFIG_PAGE_OFFSET	?= 0x80000000
-CONFIG_MEMORY_START     ?= 0x0c000000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
-
 IMAGE_OFFSET	:= $(shell printf "0x%08x" $$[$(CONFIG_PAGE_OFFSET)  + \
 					      $(CONFIG_MEMORY_START) + \
 					      $(CONFIG_BOOT_LINK_OFFSET)])
diff --git a/arch/sh/boot/compressed/head.S b/arch/sh/boot/compressed/head.S
index 4c26a19..a8399b0 100644
--- a/arch/sh/boot/compressed/head.S
+++ b/arch/sh/boot/compressed/head.S
@@ -8,6 +8,7 @@
 .text
 
 #include <linux/linkage.h>
+#include <asm/page.h>
 
 	.global	startup
 startup:
@@ -97,7 +98,7 @@
 decompress_kernel_addr:
 	.long	decompress_kernel
 kernel_start_addr:
-	.long	_text+0x1000
+	.long	_text+PAGE_SIZE
 
 	.align	9
 fake_headers_as_bzImage:
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
index 35452d8..df65e30 100644
--- a/arch/sh/boot/compressed/misc.c
+++ b/arch/sh/boot/compressed/misc.c
@@ -13,6 +13,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/addrspace.h>
+#include <asm/page.h>
 #ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
 #endif
@@ -229,7 +230,7 @@
 void decompress_kernel(void)
 {
 	output_data = 0;
-	output_ptr = P2SEGADDR((unsigned long)&_text+0x1000);
+	output_ptr = P2SEGADDR((unsigned long)&_text+PAGE_SIZE);
 	free_mem_ptr = (unsigned long)&_end;
 	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
 
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index 238c0f1..e7f8ddb 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:14:13 2006
+# Linux kernel version: 2.6.19
+# Thu Dec  7 17:13:04 2006
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -10,6 +10,9 @@
 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_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -33,6 +36,7 @@
 # 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
@@ -114,6 +118,8 @@
 CONFIG_SH_LANDISK=y
 # 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
 
 #
@@ -125,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
@@ -160,6 +172,7 @@
 #
 # 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
@@ -175,6 +188,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
@@ -196,16 +212,21 @@
 # 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_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=33333333
 
 #
@@ -216,9 +237,7 @@
 #
 # DMA support
 #
-CONFIG_SH_DMA=y
-CONFIG_NR_ONCHIP_DMA_CHANNELS=4
-# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+# CONFIG_SH_DMA is not set
 
 #
 # Companion Chips
@@ -227,6 +246,11 @@
 CONFIG_HEARTBEAT=y
 
 #
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
@@ -340,11 +364,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
 
 #
 # IP: Virtual Server Configuration
@@ -361,24 +387,12 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# 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 is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -477,6 +491,12 @@
 # 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
@@ -519,6 +539,7 @@
 # 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_IT821X is not set
@@ -542,6 +563,7 @@
 #
 # 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
 
@@ -561,6 +583,7 @@
 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
@@ -602,12 +625,12 @@
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
-# 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
@@ -615,6 +638,7 @@
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # PCMCIA SCSI adapter support
@@ -757,6 +781,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -871,10 +896,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
 
 #
@@ -889,7 +910,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -905,6 +925,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -917,10 +938,6 @@
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 CONFIG_VIDEO_DEV=m
@@ -1037,6 +1054,7 @@
 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
 
 #
@@ -1106,7 +1124,6 @@
 # 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
 
 #
 # USB Imaging devices
@@ -1121,6 +1138,7 @@
 # CONFIG_USB_KAWETH is not set
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1156,6 +1174,7 @@
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
 # CONFIG_USB_SERIAL_MOS7840 is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=m
@@ -1167,6 +1186,7 @@
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OPTION is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
 
 #
 # USB Miscellaneous drivers
@@ -1188,6 +1208,7 @@
 CONFIG_USB_SISUSBVGA=m
 CONFIG_USB_SISUSBVGA_CON=y
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1254,6 +1275,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
@@ -1264,6 +1286,7 @@
 # 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=y
@@ -1414,6 +1437,7 @@
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
@@ -1422,6 +1446,7 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
@@ -1445,6 +1470,4 @@
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 36cec0b..87ab908 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Sun Nov  5 16:20:10 2006
+# Linux kernel version: 2.6.19
+# Wed Dec  6 14:40:15 2006
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,6 +11,8 @@
 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_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -34,24 +36,23 @@
 # CONFIG_IKCONFIG is not set
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
-CONFIG_UID16=y
+# CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_TINY_SHMEM=y
-CONFIG_BASE_SMALL=0
+CONFIG_BASE_SMALL=1
 # CONFIG_SLOB is not set
 
 #
@@ -160,6 +161,7 @@
 #
 # 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
@@ -172,7 +174,10 @@
 #
 CONFIG_PAGE_OFFSET=0x00000000
 CONFIG_MEMORY_START=0x0c000000
-CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_MEMORY_SIZE=0x04000000
+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
@@ -194,6 +199,7 @@
 # Processor features
 #
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_SH_FPU is not set
 # CONFIG_SH_FPU_EMU is not set
 # CONFIG_SH_DSP is not set
@@ -203,6 +209,8 @@
 #
 CONFIG_SH_CMT=y
 # CONFIG_SH_MTU2 is not set
+CONFIG_SH_TIMER_IRQ=140
+# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=33333333
 CONFIG_SH_CLK_MD=6
 
@@ -222,6 +230,11 @@
 # CONFIG_HD6446X_SERIES is not set
 
 #
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
 # Kernel features
 #
 CONFIG_HZ_100=y
@@ -279,9 +292,6 @@
 # CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 # CONFIG_UNIX is not set
-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
@@ -297,9 +307,9 @@
 # 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_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
@@ -371,7 +381,7 @@
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
@@ -422,7 +432,7 @@
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0x1000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
 CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_SOLUTIONENGINE is not set
 # CONFIG_MTD_UCLINUX is not set
@@ -468,10 +478,7 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -519,7 +526,50 @@
 #
 # Network device support
 #
-# CONFIG_NETDEVICES is not set
+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_STNIC is not set
+CONFIG_SMC91X=y
+
+#
+# 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
 
@@ -536,7 +586,26 @@
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+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
@@ -564,8 +633,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_UNIX98_PTYS is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
 
 #
 # IPMI
@@ -576,7 +644,7 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -610,12 +678,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_F71805F is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -630,7 +694,7 @@
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
 
 #
@@ -701,8 +765,7 @@
 #
 # File systems
 #
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -755,7 +818,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_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
@@ -793,8 +856,9 @@
 #
 # 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_KERNEL is not set
@@ -819,7 +883,7 @@
 #
 # Library routines
 #
-CONFIG_CRC_CCITT=y
+# CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
new file mode 100644
index 0000000..20ac7f4
--- /dev/null
+++ b/arch/sh/configs/se7619_defconfig
@@ -0,0 +1,744 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19
+# Wed Dec  6 16:35:36 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+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_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_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SLAB=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD 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_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# 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
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# 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=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH2=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+CONFIG_CPU_SUBTYPE_SH7619=y
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# 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
+
+#
+# Memory management options
+#
+CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+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
+# 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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_SH_WRITETHROUGH=y
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+
+#
+# Timer support
+#
+CONFIG_SH_CMT=y
+CONFIG_SH_TIMER_IRQ=86
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=31250000
+CONFIG_SH_CLK_MD=5
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_KEXEC is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
+# 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=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=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 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=0xa0000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_UCLINUX 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
+#
+# 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 is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# Misc devices
+#
+# 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
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# 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 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# 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_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
+
+#
+# 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
+
+#
+# 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
+
+#
+# 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 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
+# 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 is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_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
+# 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_TRACE_IRQFLAGS_SUPPORT=y
+# 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_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS 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
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index f2b9157..b3d20c0 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -14,7 +14,7 @@
 #include <asm/push-switch.h>
 
 #define DRV_NAME "push-switch"
-#define DRV_VERSION "0.1.0"
+#define DRV_VERSION "0.1.1"
 
 static ssize_t switch_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -32,10 +32,10 @@
 	schedule_work(&psw->work);
 }
 
-static void switch_work_handler(void *data)
+static void switch_work_handler(struct work_struct *work)
 {
-	struct platform_device *pdev = data;
-	struct push_switch *psw = platform_get_drvdata(pdev);
+	struct push_switch *psw = container_of(work, struct push_switch, work);
+	struct platform_device *pdev = psw->pdev;
 
 	psw->state = 0;
 
@@ -76,12 +76,15 @@
 		}
 	}
 
-	INIT_WORK(&psw->work, switch_work_handler, pdev);
+	INIT_WORK(&psw->work, switch_work_handler);
 	init_timer(&psw->debounce);
 
 	psw->debounce.function = switch_timer;
 	psw->debounce.data = (unsigned long)psw;
 
+	/* Workqueue API brain-damage */
+	psw->pdev = pdev;
+
 	platform_set_drvdata(pdev, psw);
 
 	return 0;
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index 0582e67..d055a3e 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_CPU_SH2A)		= sh2a/
 obj-$(CONFIG_CPU_SH3)		= sh3/
 obj-$(CONFIG_CPU_SH4)		= sh4/
+obj-$(CONFIG_CPU_SH4A)		+= sh4a/
 
 obj-$(CONFIG_UBC_WAKEUP)	+= ubc.o
 obj-$(CONFIG_SH_ADC)		+= adc.o
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index 34d51b3..d51fa5e9 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -177,15 +177,21 @@
 7:	.long	do_IRQ
 8:	.long	do_exception_error
 	
-trap_entry:	
-	add	#-0x10,r9
+trap_entry:
+	/* verbose BUG trapa entry check */
+	mov	#0x3e,r8
+	cmp/ge	r8,r9
+	bf/s	1f
+	 add	#-0x10,r9
+	add	#0x10,r9
+1:	
 	shll2	r9			! TRA
 	mov	#OFF_TRA,r8
 	add	r15,r8
 	mov.l	r9,@r8
 	mov	r9,r8
 #ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	5f, r9
+	mov.l	2f, r9
 	jsr	@r9
 	 nop
 #endif
@@ -194,12 +200,8 @@
 	 nop
 	
 	.align	2
-1:	.long	syscall_exit
-2:	.long	break_point_trap_software
-3:	.long	NR_syscalls
-4:	.long	sys_call_table
 #ifdef CONFIG_TRACE_IRQFLAGS
-5:	.long	trace_hardirqs_on
+2:	.long	trace_hardirqs_on
 #endif
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
@@ -264,7 +266,7 @@
 restore_all:
 	cli
 #ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	3f, r0
+	mov.l	1f, r0
 	jsr	@r0
 	 nop
 #endif
@@ -309,20 +311,14 @@
 	mov.l	@r15,r15
 	rte
 	 nop
-2:
-	mov.l	1f,r8
-	mov.l	2f,r9
-	jmp	@r9
-	 lds	r8,pr
 
-	.align	2
+#ifdef CONFIG_TRACE_IRQFLAGS
+1:     .long   trace_hardirqs_off
+#endif
 $current_thread_info:
 	.long	__current_thread_info
 $cpu_mode:	
 	.long	__cpu_mode
-#ifdef CONFIG_TRACE_IRQFLAGS
-3:	.long	trace_hardirqs_off
-#endif
 		
 ! common exception handler
 #include "../../entry-common.S"
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 82c2d90..79283e6 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -51,3 +51,44 @@
 				    ARRAY_SIZE(sh7619_devices));
 }
 __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 },
+};
+
+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/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index cdfeef49..4b60fcc 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -17,22 +17,22 @@
 		.mapbase	= 0xfffe8000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 240, 241, 242, 243},
+		.irqs		=  { 241, 242, 243, 240},
 	}, {
 		.mapbase	= 0xfffe8800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 244, 245, 246, 247},
+		.irqs		=  { 247, 244, 245, 246},
 	}, {
 		.mapbase	= 0xfffe9000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 248, 249, 250, 251},
+		.irqs		=  { 249, 250, 251, 248},
 	}, {
 		.mapbase	= 0xfffe9800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 252, 253, 254, 255},
+		.irqs		=  { 253, 254, 255, 252},
 	}, {
 		.flags = 0,
 	}
@@ -56,3 +56,57 @@
 				    ARRAY_SIZE(sh7206_devices));
 }
 __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 },
+};
+
+void __init init_IRQ_ipr(void)
+{
+	make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 6e415ba..19ca68c7 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -12,17 +12,12 @@
 obj-$(CONFIG_CPU_SUBTYPE_SH7750)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7760)	+= setup-sh7760.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7770)	+= setup-sh7770.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= setup-sh7780.o
-obj-$(CONFIG_CPU_SUBTYPE_SH73180)	+= setup-sh73180.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= setup-sh4-202.o
 
 # Primary on-chip clocks (common)
+ifndef CONFIG_CPU_SH4A
 clock-$(CONFIG_CPU_SH4)			:= clock-sh4.o
-clock-$(CONFIG_CPU_SUBTYPE_SH73180)	:= clock-sh73180.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7770)	:= clock-sh7770.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
+endif
 
 # Additional clocks by subtype
 clock-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= clock-sh4-202.o
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index afe0f1b..9031a22 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -119,11 +119,20 @@
 		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;
 		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;
+		}
+		break;
 	case 0x8000:
 		cpu_data->type = CPU_ST40RA;
 		cpu_data->flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index bbcb06f..cbac276 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -14,6 +14,36 @@
 #include <linux/io.h>
 #include <asm/sci.h>
 
+static struct resource rtc_resources[] = {
+	[0] = {
+		.start	= 0xffc80000,
+		.end	= 0xffc80000 + 0x58 - 1,
+		.flags	= IORESOURCE_IO,
+	},
+	[1] = {
+		/* Period IRQ */
+		.start	= 21,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* Carry IRQ */
+		.start	= 22,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		/* Alarm IRQ */
+		.start	= 20,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device rtc_device = {
+	.name		= "sh-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+	.resource	= rtc_resources,
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
@@ -39,6 +69,7 @@
 };
 
 static struct platform_device *sh7750_devices[] __initdata = {
+	&rtc_device,
 	&sci_device,
 };
 
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 0c9ea38..d7fff75 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -111,8 +111,9 @@
 
 	vma->phys_addr = map->addr;
 
-	if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr,
-			     map->size, flags)) {
+	if (ioremap_page_range((unsigned long)vma->addr,
+			       (unsigned long)vma->addr + map->size,
+			       vma->phys_addr, __pgprot(flags))) {
 		vunmap(vma->addr);
 		return -EAGAIN;
 	}
@@ -176,7 +177,7 @@
 
 	map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
 
-	ret = __sq_remap(map, flags);
+	ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
 	if (unlikely(ret != 0))
 		goto out;
 
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
new file mode 100644
index 0000000..a8f493f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the Linux/SuperH SH-4 backends.
+#
+
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7770)	+= setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180)	+= setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722)	+= setup-sh7722.o
+
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SUBTYPE_SH73180)	:= clock-sh73180.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7770)	:= clock-sh7770.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7343.o
+
+obj-y	+= $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/clock-sh73180.c
rename to arch/sh/kernel/cpu/sh4a/clock-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
new file mode 100644
index 0000000..1707a21
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7343.c
+ *
+ * SH7343/SH7722 support for the clock framework
+ *
+ *  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/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+/*
+ * SH7343/SH7722 uses a common set of multipliers and divisors, so this
+ * is quite simple..
+ */
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
+
+static void master_clk_init(struct clk *clk)
+{
+	clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void master_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQCR) & 0x000f);
+	clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_master_clk_ops = {
+	.init		= master_clk_init,
+	.recalc		= master_clk_recalc,
+};
+
+static void module_clk_init(struct clk *clk)
+{
+	clk->parent = NULL;
+	clk->rate = CONFIG_SH_PCLK_FREQ;
+}
+
+static struct clk_ops sh7343_module_clk_ops = {
+	.init		= module_clk_init,
+};
+
+static void bus_clk_init(struct clk *clk)
+{
+	clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void bus_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
+	clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_bus_clk_ops = {
+	.init		= bus_clk_init,
+	.recalc		= bus_clk_recalc,
+};
+
+static void cpu_clk_init(struct clk *clk)
+{
+	clk->parent = clk_get(NULL, "module_clk");
+	clk->flags |= CLK_RATE_PROPAGATES;
+	clk_set_rate(clk, clk_get_rate(clk));
+}
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
+	clk->rate = clk->parent->rate * pll_calc() *
+		multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_cpu_clk_ops = {
+	.init		= cpu_clk_init,
+	.recalc		= cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7343_clk_ops[] = {
+	&sh7343_master_clk_ops,
+	&sh7343_module_clk_ops,
+	&sh7343_bus_clk_ops,
+	&sh7343_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+	if (idx < ARRAY_SIZE(sh7343_clk_ops))
+		*ops = sh7343_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/clock-sh7770.c
rename to arch/sh/kernel/cpu/sh4a/clock-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/clock-sh7780.c
rename to arch/sh/kernel/cpu/sh4a/clock-sh7780.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4a/setup-sh73180.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh73180.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh7343.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh7343.c
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
new file mode 100644
index 0000000..1143fbf
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -0,0 +1,80 @@
+/*
+ * SH7722 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase	= 0xffe00000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 80, 81, 83, 82 },
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+static struct platform_device *sh7722_devices[] __initdata = {
+	&sci_device,
+};
+
+static int __init sh7722_devices_setup(void)
+{
+	return platform_add_devices(sh7722_devices,
+				    ARRAY_SIZE(sh7722_devices));
+}
+__initcall(sh7722_devices_setup);
+
+static struct ipr_data sh7722_ipr_map[] = {
+	/* IRQ, IPR-idx, shift, prio */
+	{ 16, 0, 12, 2 }, /* TMU0 */
+	{ 17, 0,  8, 2 }, /* TMU1 */
+	{ 80, 6, 12, 3 }, /* SCIF ERI */
+	{ 81, 6, 12, 3 }, /* SCIF RXI */
+	{ 82, 6, 12, 3 }, /* SCIF BRI */
+	{ 83, 6, 12, 3 }, /* SCIF TXI */
+};
+
+static unsigned long ipr_offsets[] = {
+	0xa4080000, /*  0: IPRA */
+	0xa4080004, /*  1: IPRB */
+	0xa4080008, /*  2: IPRC */
+	0xa408000c, /*  3: IPRD */
+	0xa4080010, /*  4: IPRE */
+	0xa4080014, /*  5: IPRF */
+	0xa4080018, /*  6: IPRG */
+	0xa408001c, /*  7: IPRH */
+	0xa4080020, /*  8: IPRI */
+	0xa4080024, /*  9: IPRJ */
+	0xa4080028, /* 10: IPRK */
+	0xa408002c, /* 11: IPRL */
+};
+
+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(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh7770.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh7780.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh7780.c
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 6034082..560b91c 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -144,16 +144,16 @@
 	;
 
 static int __initdata keep_early;
+static int early_console_initialized;
 
-int __init setup_early_printk(char *opt)
+int __init setup_early_printk(char *buf)
 {
-	char *space;
-	char buf[256];
+	if (!buf)
+		return 0;
 
-	strlcpy(buf, opt, sizeof(buf));
-	space = strchr(buf, ' ');
-	if (space)
-		*space = 0;
+	if (early_console_initialized)
+		return 0;
+	early_console_initialized = 1;
 
 	if (strstr(buf, "keep"))
 		keep_early = 1;
@@ -175,12 +175,14 @@
 	if (likely(early_console))
 		register_console(early_console);
 
-	return 1;
+	return 0;
 }
-__setup("earlyprintk=", setup_early_printk);
+early_param("earlyprintk", setup_early_printk);
 
 void __init disable_early_printk(void)
 {
+	if (!early_console_initialized || !early_console)
+		return;
 	if (!keep_early) {
 		printk("disabling early console\n");
 		unregister_console(early_console);
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index 29136a3..fc279ae 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -79,18 +79,29 @@
 	.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
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index 6aca4bc..71a3ad7 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -33,7 +33,8 @@
 	.long	0x00360000	/* INITRD_START */
 	.long	0x000a0000	/* INITRD_SIZE */
 	.long	0
-	.balign PAGE_SIZE,0,PAGE_SIZE
+1:
+	.skip	PAGE_SIZE - empty_zero_page - 1b
 
 	.text	
 /*
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index f3e2631..486c06e 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -470,9 +470,10 @@
 	 */
 	pc = thread_saved_pc(p);
 	if (in_sched_functions(pc)) {
-		schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
-		return (unsigned long)((unsigned long *)schedule_frame)[1];
+		schedule_frame = (unsigned long)p->thread.sp;
+		return ((unsigned long *)schedule_frame)[21];
 	}
+
 	return pc;
 }
 
@@ -498,6 +499,16 @@
 {
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
+	/* Rewind */
 	regs->pc -= 2;
+
+#ifdef CONFIG_BUG
+	if (__kernel_text_address(instruction_pointer(regs))) {
+		u16 insn = *(u16 *)instruction_pointer(regs);
+		if (insn == TRAPA_BUG_OPCODE)
+			handle_BUG(regs);
+	}
+#endif
+
 	force_sig(SIGTRAP, current);
 }
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index f8dd6b7..225f9ea 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -84,8 +84,7 @@
 
 static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
 				  struct sh_machine_vector** mvp,
-				  unsigned long *mv_io_base,
-				  int *mv_mmio_enable)
+				  unsigned long *mv_io_base)
 {
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
 	int len = 0;
@@ -112,23 +111,6 @@
 			}
 		}
 
-#ifdef CONFIG_EARLY_PRINTK
-		if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
-			char *ep_end;
-
-			if (to != command_line)
-				to--;
-
-			from += 12;
-			ep_end = strchr(from, ' ');
-
-			setup_early_printk(from);
-			printk("early console enabled\n");
-
-			from = ep_end;
-		}
-#endif
-
 		if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
 			char* mv_end;
 			char* mv_comma;
@@ -145,7 +127,6 @@
 				int ints[3];
 				get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
 				*mv_io_base = ints[1];
-				*mv_mmio_enable = ints[2];
 				mv_len = mv_comma - from;
 			} else {
 				mv_len = mv_end - from;
@@ -158,6 +139,7 @@
 
 			*mvp = get_mv_byname(mv_name);
 		}
+
 		c = *(from++);
 		if (!c)
 			break;
@@ -177,9 +159,8 @@
 	struct sh_machine_vector *mv = NULL;
 	char mv_name[MV_NAME_SIZE] = "";
 	unsigned long mv_io_base = 0;
-	int mv_mmio_enable = 0;
 
-	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
+	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
 
 #ifdef CONFIG_SH_UNKNOWN
 	if (mv == NULL) {
@@ -258,6 +239,7 @@
 
 	sh_mv_setup(cmdline_p);
 
+
 	/*
 	 * Find the highest page frame number we have available
 	 */
@@ -305,6 +287,7 @@
 				  PFN_PHYS(pages));
 	}
 
+
 	/*
 	 * Reserve the kernel text and
 	 * Reserve the bootmem bitmap. We do this in two steps (first step
@@ -325,14 +308,18 @@
 	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
 	if (&__rd_start != &__rd_end) {
 		LOADER_TYPE = 1;
-		INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
-		INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
+		INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
+					__MEMORY_START;
+		INITRD_SIZE = (unsigned long)&__rd_end -
+			      (unsigned long)&__rd_start;
 	}
 
 	if (LOADER_TYPE && INITRD_START) {
 		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-			reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
-			initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START;
+			reserve_bootmem_node(NODE_DATA(0), INITRD_START +
+						__MEMORY_START, INITRD_SIZE);
+			initrd_start = INITRD_START + PAGE_OFFSET +
+					__MEMORY_START;
 			initrd_end = initrd_start + INITRD_SIZE;
 		} else {
 			printk("initrd extends beyond end of memory "
@@ -404,7 +391,7 @@
 	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
 	[CPU_SH7770]	= "SH7770",	[CPU_SH7780]	= "SH7780",
 	[CPU_SH7781]	= "SH7781",	[CPU_SH7343]	= "SH7343",
-	[CPU_SH7785]	= "SH7785",
+	[CPU_SH7785]	= "SH7785",	[CPU_SH7722]	= "SH7722",
 	[CPU_SH_NONE]	= "Unknown"
 };
 
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index ceee791..e610623 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -70,13 +70,26 @@
 DECLARE_EXPORT(__ashrdi3);
 DECLARE_EXPORT(__ashldi3);
 DECLARE_EXPORT(__lshrdi3);
-DECLARE_EXPORT(__movstr);
 DECLARE_EXPORT(__movstrSI16);
+#if __GNUC__ == 4
+DECLARE_EXPORT(__movmem);
+#else
+DECLARE_EXPORT(__movstr);
+#endif
 
 #ifdef CONFIG_CPU_SH4
+#if __GNUC__ == 4
+DECLARE_EXPORT(__movmem_i4_even);
+DECLARE_EXPORT(__movmem_i4_odd);
+DECLARE_EXPORT(__movmemSI12_i4);
+DECLARE_EXPORT(__sdivsi3_i4i);
+DECLARE_EXPORT(__udiv_qrnnd_16);
+DECLARE_EXPORT(__udivsi3_i4i);
+#else /* GCC 3.x */
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
 DECLARE_EXPORT(__movstrSI12_i4);
+#endif /* __GNUC__ == 4 */
 #endif
 
 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index bb1c480..379c88b 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -101,7 +101,7 @@
  */
 
 #define MOVW(n)	 (0x9300|((n)-2))	/* Move mem word at PC+n to R3 */
-#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
+#if defined(CONFIG_CPU_SH2)
 #define TRAP_NOARG 0xc320		/* Syscall w/no args (NR in R3) */
 #else
 #define TRAP_NOARG 0xc310		/* Syscall w/no args (NR in R3) */
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 5083b6e..e18f183 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -314,6 +314,12 @@
 #endif
 }
 
+#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
+#define SYSCALL_ARG3	"trapa #0x23"
+#else
+#define SYSCALL_ARG3	"trapa #0x13"
+#endif
+
 /*
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
@@ -324,7 +330,7 @@
 	register long __sc4 __asm__ ("r4") = (long) filename;
 	register long __sc5 __asm__ ("r5") = (long) argv;
 	register long __sc6 __asm__ ("r6") = (long) envp;
-	__asm__ __volatile__ ("trapa	#0x13" : "=z" (__sc0)
+	__asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)	
 			: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
 			: "memory");
 	return __sc0;
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 3762d9d..ec11015 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -19,6 +19,7 @@
 #include <linux/kallsyms.h>
 #include <linux/io.h>
 #include <linux/debug_locks.h>
+#include <linux/limits.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
@@ -129,6 +130,40 @@
 	return -EFAULT;
 }
 
+#ifdef CONFIG_BUG
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+static inline void do_bug_verbose(struct pt_regs *regs)
+{
+	struct bug_frame f;
+	long len;
+
+	if (__copy_from_user(&f, (const void __user *)regs->pc,
+			     sizeof(struct bug_frame)))
+		return;
+
+	len = __strnlen_user(f.file, PATH_MAX) - 1;
+	if (unlikely(len < 0 || len >= PATH_MAX))
+		f.file = "<bad filename>";
+	len = __strnlen_user(f.func, PATH_MAX) - 1;
+	if (unlikely(len < 0 || len >= PATH_MAX))
+		f.func = "<bad function>";
+
+	printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n",
+	       f.func, f.file, f.line);
+}
+#else
+static inline void do_bug_verbose(struct pt_regs *regs)
+{
+}
+#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);
+}
+
 /*
  * handle an instruction that does an unaligned memory access by emulating the
  * desired behaviour
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 77b4026..f34bdcc 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -51,7 +51,7 @@
 	}
 
   . = ALIGN(PAGE_SIZE);
-  .data.page_aligned : { *(.data.idt) }
+  .data.page_aligned : { *(.data.page_aligned) }
 
   . = ALIGN(32);
   __per_cpu_start = .;
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 4e0362f..29f4ee3 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -35,6 +35,9 @@
 	select CPU_SH4
 	select CPU_HAS_INTC2_IRQ
 
+config CPU_SHX2
+	bool
+
 #
 # Processor subtypes
 #
@@ -180,6 +183,7 @@
 config CPU_SUBTYPE_SH7785
 	bool "Support SH7785 processor"
 	select CPU_SH4A
+	select CPU_SHX2
 	select CPU_HAS_INTC2_IRQ
 
 comment "SH4AL-DSP Processor Support"
@@ -192,6 +196,12 @@
 	bool "Support SH7343 processor"
 	select CPU_SH4AL_DSP
 
+config CPU_SUBTYPE_SH7722
+	bool "Support SH7722 processor"
+	select CPU_SH4AL_DSP
+	select CPU_SHX2
+	select CPU_HAS_IPR_IRQ
+
 endmenu
 
 menu "Memory management options"
@@ -250,7 +260,7 @@
 
 config X2TLB
 	bool "Enable extended TLB mode"
-	depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
+	depends on CPU_SHX2 && MMU && EXPERIMENTAL
 	help
 	  Selecting this option will enable the extended mode of the SH-X2
 	  TLB. For legacy SH-X behaviour and interoperability, say N. For
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index ae531af..c695515 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -107,7 +107,7 @@
 
 	emit_cache_params();
 
-	if (remap_area_pages(P3SEG, 0, PAGE_SIZE * 4, _PAGE_CACHABLE))
+	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++)
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 59f4cc1..29bd37b 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -77,6 +77,7 @@
 	printk("%d pages swap cached\n",cached);
 }
 
+#ifdef CONFIG_MMU
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
 {
 	pgd_t *pgd;
@@ -139,6 +140,7 @@
 
 	set_pte_phys(address, phys, prot);
 }
+#endif	/* CONFIG_MMU */
 
 /* References to section boundaries */
 
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 3ac581d..d427553 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -584,7 +584,7 @@
 	  If unsure, say Y. Only embedded should say N here.
 
 config CC_STACKPROTECTOR
-	bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)"
+	bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	help
          This option turns on the -fstack-protector GCC feature. This
diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
index 81f1562..3abcfa3 100644
--- a/arch/x86_64/kernel/cpufreq/Kconfig
+++ b/arch/x86_64/kernel/cpufreq/Kconfig
@@ -27,10 +27,13 @@
 	default y
 
 config X86_SPEEDSTEP_CENTRINO
-	tristate "Intel Enhanced SpeedStep"
+	tristate "Intel Enhanced SpeedStep (deprecated)"
 	select CPU_FREQ_TABLE
 	depends on ACPI_PROCESSOR
 	help
+	  This is deprecated and this functionality is now merged into
+	  acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
+	  speedstep_centrino.
 	  This adds the CPUFreq driver for Enhanced SpeedStep enabled
 	  mobile CPUs.  This means Intel Pentium M (Centrino) CPUs
 	  or 64bit enabled Intel Xeons.
@@ -50,6 +53,7 @@
 	help
 	  This driver adds a CPUFreq driver which utilizes the ACPI
 	  Processor Performance States.
+	  This driver also supports Intel Enhanced Speedstep.
 
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
diff --git a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile
index d8b5938..753ce1d 100644
--- a/arch/x86_64/kernel/cpufreq/Makefile
+++ b/arch/x86_64/kernel/cpufreq/Makefile
@@ -5,8 +5,8 @@
 SRCDIR := ../../../i386/kernel/cpu/cpufreq
 
 obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
-obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
 obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
 obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
 obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o
 
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 785e61c..a541b42 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -129,13 +129,6 @@
 }
 EXPORT_SYMBOL(blk_get_backing_dev_info);
 
-void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data)
-{
-	q->activity_fn = fn;
-	q->activity_data = data;
-}
-EXPORT_SYMBOL(blk_queue_activity_fn);
-
 /**
  * blk_queue_prep_rq - set a prepare_request function for queue
  * @q:		queue
@@ -238,8 +231,6 @@
 	 * by default assume old behaviour and bounce for any highmem page
 	 */
 	blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
-
-	blk_queue_activity_fn(q, NULL, NULL);
 }
 
 EXPORT_SYMBOL(blk_queue_make_request);
@@ -2696,9 +2687,6 @@
 {
 	drive_stat_acct(req, req->nr_sectors, 1);
 
-	if (q->activity_fn)
-		q->activity_fn(q->activity_data, rq_data_dir(req));
-
 	/*
 	 * elevator indicated where it wants this request to be
 	 * inserted at elevator_merge time
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index b3e2107..f322b6a 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -228,6 +228,7 @@
 	struct request *rq;
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	unsigned char cmd[BLK_MAX_CDB];
+	struct bio *bio;
 
 	if (hdr->interface_id != 'S')
 		return -EINVAL;
@@ -270,13 +271,6 @@
 
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 
-	/*
-	 * bounce this after holding a reference to the original bio, it's
-	 * needed for proper unmapping
-	 */
-	if (rq->bio)
-		blk_queue_bounce(q, &rq->bio);
-
 	rq->timeout = jiffies_to_msecs(hdr->timeout);
 	if (!rq->timeout)
 		rq->timeout = q->sg_timeout;
@@ -308,6 +302,7 @@
 	if (ret)
 		goto out;
 
+	bio = rq->bio;
 	rq->retries = 0;
 
 	start_time = jiffies;
@@ -338,6 +333,7 @@
 			hdr->sb_len_wr = len;
 	}
 
+	rq->bio = bio;
 	if (blk_rq_unmap_user(rq))
 		ret = -EFAULT;
 
diff --git a/crypto/sha512.c b/crypto/sha512.c
index 2dfe7f1..15eab9d 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -24,7 +24,7 @@
 
 #define SHA384_DIGEST_SIZE 48
 #define SHA512_DIGEST_SIZE 64
-#define SHA384_HMAC_BLOCK_SIZE  96
+#define SHA384_HMAC_BLOCK_SIZE 128
 #define SHA512_HMAC_BLOCK_SIZE 128
 
 struct sha512_ctx {
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index bdb9c8b..9e584a7 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -360,7 +360,7 @@
 	if (ret >= 0){
 		ret = misc_register(&rtc_dev);
 		if(ret < 0)
-			i2c_bit_del_bus(&ioc_ops);
+			i2c_del_adapter(&ioc_ops);
 	}
 
 	return ret;
diff --git a/drivers/atm/.gitignore b/drivers/atm/.gitignore
index a165b71..fc0ae5e 100644
--- a/drivers/atm/.gitignore
+++ b/drivers/atm/.gitignore
@@ -2,4 +2,4 @@
 fore200e_mkfirm
 fore200e_pca_fw.c
 pca200e.bin
-
+pca200e_ecd.bin2
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 47ab42d..9fb2edf 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -29,7 +29,8 @@
 #include <linux/completion.h>
 #include <linux/mutex.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
+						"cpufreq-core", msg)
 
 /**
  * The "cpufreq driver" - the arch- or hardware-dependent low
@@ -151,7 +152,8 @@
 	spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
 }
 
-void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt, ...)
+void cpufreq_debug_printk(unsigned int type, const char *prefix,
+							const char *fmt, ...)
 {
 	char s[256];
 	va_list args;
@@ -161,7 +163,8 @@
 	WARN_ON(!prefix);
 	if (type & debug) {
 		spin_lock_irqsave(&disable_ratelimit_lock, flags);
-		if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit()) {
+		if (!disable_ratelimit && debug_ratelimit
+					&& !printk_ratelimit()) {
 			spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
 			return;
 		}
@@ -182,10 +185,12 @@
 
 
 module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors.");
+MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core,"
+			" 2 to debug drivers, and 4 to debug governors.");
 
 module_param(debug_ratelimit, uint, 0644);
-MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging: set to 0 to disable ratelimiting.");
+MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging:"
+					" set to 0 to disable ratelimiting.");
 
 #else /* !CONFIG_CPU_FREQ_DEBUG */
 
@@ -219,17 +224,23 @@
 	if (!l_p_j_ref_freq) {
 		l_p_j_ref = loops_per_jiffy;
 		l_p_j_ref_freq = ci->old;
-		dprintk("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
+		dprintk("saving %lu as reference value for loops_per_jiffy;"
+			"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
 	}
 	if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
 	    (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
 	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
-		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
-		dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new);
+		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
+								ci->new);
+		dprintk("scaling loops_per_jiffy to %lu"
+			"for frequency %u kHz\n", loops_per_jiffy, ci->new);
 	}
 }
 #else
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+{
+	return;
+}
 #endif
 
 
@@ -316,7 +327,8 @@
 		if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
 			*policy = CPUFREQ_POLICY_PERFORMANCE;
 			err = 0;
-		} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
+		} else if (!strnicmp(str_governor, "powersave",
+						CPUFREQ_NAME_LEN)) {
 			*policy = CPUFREQ_POLICY_POWERSAVE;
 			err = 0;
 		}
@@ -328,7 +340,8 @@
 		t = __find_governor(str_governor);
 
 		if (t == NULL) {
-			char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor);
+			char *name = kasprintf(GFP_KERNEL, "cpufreq_%s",
+								str_governor);
 
 			if (name) {
 				int ret;
@@ -361,7 +374,8 @@
 
 
 /**
- * cpufreq_per_cpu_attr_read() / show_##file_name() - print out cpufreq information
+ * cpufreq_per_cpu_attr_read() / show_##file_name() -
+ * print out cpufreq information
  *
  * Write out information from cpufreq_driver->policy[cpu]; object must be
  * "unsigned int".
@@ -380,7 +394,8 @@
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
 
-static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
+static int __cpufreq_set_policy(struct cpufreq_policy *data,
+				struct cpufreq_policy *policy);
 
 /**
  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
@@ -416,7 +431,8 @@
 /**
  * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
  */
-static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, char *buf)
+static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
+							char *buf)
 {
 	unsigned int cur_freq = cpufreq_get(policy->cpu);
 	if (!cur_freq)
@@ -428,7 +444,8 @@
 /**
  * show_scaling_governor - show the current policy for the specified CPU
  */
-static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
+static ssize_t show_scaling_governor (struct cpufreq_policy * policy,
+							char *buf)
 {
 	if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
 		return sprintf(buf, "powersave\n");
@@ -458,7 +475,8 @@
 	if (ret != 1)
 		return -EINVAL;
 
-	if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
+	if (cpufreq_parse_governor(str_governor, &new_policy.policy,
+						&new_policy.governor))
 		return -EINVAL;
 
 	lock_cpu_hotplug();
@@ -474,7 +492,10 @@
 
 	unlock_cpu_hotplug();
 
-	return ret ? ret : count;
+	if (ret)
+		return ret;
+	else
+		return count;
 }
 
 /**
@@ -488,7 +509,7 @@
 /**
  * show_scaling_available_governors - show the available CPUfreq governors
  */
-static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
+static ssize_t show_scaling_available_governors (struct cpufreq_policy *policy,
 				char *buf)
 {
 	ssize_t i = 0;
@@ -574,7 +595,11 @@
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
-	ret = fattr->show ? fattr->show(policy,buf) : -EIO;
+	if (fattr->show)
+		ret = fattr->show(policy, buf);
+	else
+		ret = -EIO;
+
 	cpufreq_cpu_put(policy);
 	return ret;
 }
@@ -588,7 +613,11 @@
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
-	ret = fattr->store ? fattr->store(policy,buf,count) : -EIO;
+	if (fattr->store)
+		ret = fattr->store(policy, buf, count);
+	else
+		ret = -EIO;
+
 	cpufreq_cpu_put(policy);
 	return ret;
 }
@@ -913,7 +942,8 @@
  *	We adjust to current frequency first, and need to clean up later. So either call
  *	to cpufreq_update_policy() or schedule handle_update()).
  */
-static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int new_freq)
+static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
+				unsigned int new_freq)
 {
 	struct cpufreq_freqs freqs;
 
@@ -938,16 +968,16 @@
 unsigned int cpufreq_quick_get(unsigned int cpu)
 {
 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-	unsigned int ret = 0;
+	unsigned int ret_freq = 0;
 
 	if (policy) {
 		mutex_lock(&policy->lock);
-		ret = policy->cur;
+		ret_freq = policy->cur;
 		mutex_unlock(&policy->lock);
 		cpufreq_cpu_put(policy);
 	}
 
-	return (ret);
+	return (ret_freq);
 }
 EXPORT_SYMBOL(cpufreq_quick_get);
 
@@ -961,7 +991,7 @@
 unsigned int cpufreq_get(unsigned int cpu)
 {
 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-	unsigned int ret = 0;
+	unsigned int ret_freq = 0;
 
 	if (!policy)
 		return 0;
@@ -971,12 +1001,14 @@
 
 	mutex_lock(&policy->lock);
 
-	ret = cpufreq_driver->get(cpu);
+	ret_freq = cpufreq_driver->get(cpu);
 
-	if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
-		/* verify no discrepancy between actual and saved value exists */
-		if (unlikely(ret != policy->cur)) {
-			cpufreq_out_of_sync(cpu, policy->cur, ret);
+	if (ret_freq && policy->cur &&
+		!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
+		/* verify no discrepancy between actual and
+					saved value exists */
+		if (unlikely(ret_freq != policy->cur)) {
+			cpufreq_out_of_sync(cpu, policy->cur, ret_freq);
 			schedule_work(&policy->update);
 		}
 	}
@@ -986,7 +1018,7 @@
 out:
 	cpufreq_cpu_put(policy);
 
-	return (ret);
+	return (ret_freq);
 }
 EXPORT_SYMBOL(cpufreq_get);
 
@@ -998,7 +1030,7 @@
 static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
 {
 	int cpu = sysdev->id;
-	unsigned int ret = 0;
+	int ret = 0;
 	unsigned int cur_freq = 0;
 	struct cpufreq_policy *cpu_policy;
 
@@ -1080,7 +1112,7 @@
 static int cpufreq_resume(struct sys_device * sysdev)
 {
 	int cpu = sysdev->id;
-	unsigned int ret = 0;
+	int ret = 0;
 	struct cpufreq_policy *cpu_policy;
 
 	dprintk("resuming cpu %u\n", cpu);
@@ -1276,22 +1308,45 @@
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
+int cpufreq_driver_getavg(struct cpufreq_policy *policy)
+{
+	int ret = 0;
+
+	policy = cpufreq_cpu_get(policy->cpu);
+	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);
+
 /*
  * Locking: Must be called with the lock_cpu_hotplug() lock held
  * when "event" is CPUFREQ_GOV_LIMITS
  */
 
-static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
+static int __cpufreq_governor(struct cpufreq_policy *policy,
+					unsigned int event)
 {
 	int ret;
 
 	if (!try_module_get(policy->governor->owner))
 		return -EINVAL;
 
-	dprintk("__cpufreq_governor for CPU %u, event %u\n", policy->cpu, event);
+	dprintk("__cpufreq_governor for CPU %u, event %u\n",
+						policy->cpu, event);
 	ret = policy->governor->governor(policy, event);
 
-	/* we keep one module reference alive for each CPU governed by this CPU */
+	/* we keep one module reference alive for
+			each CPU governed by this CPU */
 	if ((event != CPUFREQ_GOV_START) || ret)
 		module_put(policy->governor->owner);
 	if ((event == CPUFREQ_GOV_STOP) && !ret)
@@ -1367,9 +1422,12 @@
 
 
 /*
+ * 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)
+static int __cpufreq_set_policy(struct cpufreq_policy *data,
+				struct cpufreq_policy *policy)
 {
 	int ret = 0;
 
@@ -1377,7 +1435,8 @@
 	dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
 		policy->min, policy->max);
 
-	memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
+	memcpy(&policy->cpuinfo, &data->cpuinfo,
+				sizeof(struct cpufreq_cpuinfo));
 
 	if (policy->min > data->min && policy->min > policy->max) {
 		ret = -EINVAL;
@@ -1410,7 +1469,8 @@
 	data->min = policy->min;
 	data->max = policy->max;
 
-	dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max);
+	dprintk("new min and max freqs are %u - %u kHz\n",
+					data->min, data->max);
 
 	if (cpufreq_driver->setpolicy) {
 		data->policy = policy->policy;
@@ -1431,10 +1491,12 @@
 			data->governor = policy->governor;
 			if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
 				/* new governor failed, so re-start old one */
-				dprintk("starting governor %s failed\n", data->governor->name);
+				dprintk("starting governor %s failed\n",
+							data->governor->name);
 				if (old_gov) {
 					data->governor = old_gov;
-					__cpufreq_governor(data, CPUFREQ_GOV_START);
+					__cpufreq_governor(data,
+							   CPUFREQ_GOV_START);
 				}
 				ret = -EINVAL;
 				goto error_out;
@@ -1524,7 +1586,8 @@
 			data->cur = policy.cur;
 		} else {
 			if (data->cur != policy.cur)
-				cpufreq_out_of_sync(cpu, data->cur, policy.cur);
+				cpufreq_out_of_sync(cpu, data->cur,
+								policy.cur);
 		}
 	}
 
@@ -1626,8 +1689,10 @@
 
 		/* if all ->init() calls failed, unregister */
 		if (ret) {
-			dprintk("no CPU initialized for driver %s\n", driver_data->name);
-			sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
+			dprintk("no CPU initialized for driver %s\n",
+							driver_data->name);
+			sysdev_driver_unregister(&cpu_sysdev_class,
+						&cpufreq_sysdev_driver);
 
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			cpufreq_driver = NULL;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 5ef5ede..eef0270 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -44,15 +44,17 @@
  * latency of the processor. The governor will work on any processor with 
  * transition latency <= 10mS, using appropriate sampling 
  * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
+ * For CPUs with transition latency > 10mS (mostly drivers
+ * with CPUFREQ_ETERNAL), this governor will not work.
  * All times here are in uS.
  */
 static unsigned int 				def_sampling_rate;
 #define MIN_SAMPLING_RATE_RATIO			(2)
 /* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+#define MIN_STAT_SAMPLING_RATE			\
+			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE			\
+			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
 #define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
 #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
@@ -103,11 +105,16 @@
 
 static inline unsigned int get_cpu_idle_time(unsigned int cpu)
 {
-	return	kstat_cpu(cpu).cpustat.idle +
+	unsigned int add_nice = 0, ret;
+
+	if (dbs_tuners_ins.ignore_nice)
+		add_nice = kstat_cpu(cpu).cpustat.nice;
+
+	ret = 	kstat_cpu(cpu).cpustat.idle +
 		kstat_cpu(cpu).cpustat.iowait +
-		( dbs_tuners_ins.ignore_nice ?
-		  kstat_cpu(cpu).cpustat.nice :
-		  0);
+		add_nice;
+
+	return ret;
 }
 
 /************************** sysfs interface ************************/
@@ -452,6 +459,7 @@
 	unsigned int cpu = policy->cpu;
 	struct cpu_dbs_info_s *this_dbs_info;
 	unsigned int j;
+	int rc;
 
 	this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
 
@@ -468,6 +476,13 @@
 			break;
 		 
 		mutex_lock(&dbs_mutex);
+
+		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
+		if (rc) {
+			mutex_unlock(&dbs_mutex);
+			return rc;
+		}
+
 		for_each_cpu_mask(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
 			j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -480,7 +495,7 @@
 		this_dbs_info->enable = 1;
 		this_dbs_info->down_skip = 0;
 		this_dbs_info->requested_freq = policy->cur;
-		sysfs_create_group(&policy->kobj, &dbs_attr_group);
+
 		dbs_enable++;
 		/*
 		 * Start the timerschedule work, when this governor
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index e1cc511..f697449 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -41,8 +41,10 @@
 static unsigned int def_sampling_rate;
 #define MIN_SAMPLING_RATE_RATIO			(2)
 /* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+#define MIN_STAT_SAMPLING_RATE 			\
+			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE			\
+			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
 #define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
 #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000)
@@ -206,7 +208,8 @@
 	ret = sscanf(buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
+	if (ret != 1 || input > MAX_SAMPLING_RATE
+		     || input < MIN_SAMPLING_RATE) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
@@ -397,8 +400,15 @@
 	 * policy. To be safe, we focus 10 points under the threshold.
 	 */
 	if (load < (dbs_tuners_ins.up_threshold - 10)) {
-		unsigned int freq_next = (policy->cur * load) /
+		unsigned int freq_next, freq_cur;
+
+		freq_cur = cpufreq_driver_getavg(policy);
+		if (!freq_cur)
+			freq_cur = policy->cur;
+
+		freq_next = (freq_cur * load) /
 			(dbs_tuners_ins.up_threshold - 10);
+
 		if (!dbs_tuners_ins.powersave_bias) {
 			__cpufreq_driver_target(policy, freq_next,
 					CPUFREQ_RELATION_L);
@@ -472,6 +482,7 @@
 	unsigned int cpu = policy->cpu;
 	struct cpu_dbs_info_s *this_dbs_info;
 	unsigned int j;
+	int rc;
 
 	this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
 
@@ -494,12 +505,23 @@
 		if (dbs_enable == 1) {
 			kondemand_wq = create_workqueue("kondemand");
 			if (!kondemand_wq) {
-				printk(KERN_ERR "Creation of kondemand failed\n");
+				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;
+		}
+
 		for_each_cpu_mask(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
 			j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -509,7 +531,6 @@
 			j_dbs_info->prev_cpu_wall = get_jiffies_64();
 		}
 		this_dbs_info->enable = 1;
-		sysfs_create_group(&policy->kobj, &dbs_attr_group);
 		/*
 		 * Start the timerschedule work, when this governor
 		 * is used for first time
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index de91e33..e8e1451 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -15,7 +15,8 @@
 #include <linux/cpufreq.h>
 #include <linux/init.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg)
+#define dprintk(msg...) \
+	cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg)
 
 
 static int cpufreq_governor_performance(struct cpufreq_policy *policy,
@@ -24,8 +25,10 @@
 	switch (event) {
 	case CPUFREQ_GOV_START:
 	case CPUFREQ_GOV_LIMITS:
-		dprintk("setting to %u kHz because of event %u\n", policy->max, event);
-		__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
+		dprintk("setting to %u kHz because of event %u\n",
+						policy->max, event);
+		__cpufreq_driver_target(policy, policy->max,
+						CPUFREQ_RELATION_H);
 		break;
 	default:
 		break;
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 0a25960..13fe06b 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -15,7 +15,8 @@
 #include <linux/cpufreq.h>
 #include <linux/init.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg)
+#define dprintk(msg...) \
+	cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg)
 
 static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
 					unsigned int event)
@@ -23,8 +24,10 @@
 	switch (event) {
 	case CPUFREQ_GOV_START:
 	case CPUFREQ_GOV_LIMITS:
-		dprintk("setting to %u kHz because of event %u\n", policy->min, event);
-		__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
+		dprintk("setting to %u kHz because of event %u\n",
+							policy->min, event);
+		__cpufreq_driver_target(policy, policy->min,
+						CPUFREQ_RELATION_L);
 		break;
 	default:
 		break;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index c2ecc59..6742b1a 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -351,8 +351,8 @@
 
 	register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
 	for_each_online_cpu(cpu) {
-		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE,
-			(void *)(long)cpu);
+		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier,
+				CPU_ONLINE, (void *)(long)cpu);
 	}
 	return 0;
 }
@@ -368,14 +368,15 @@
 	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);
+		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>");
-MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem");
+MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats"
+				"through sysfs filesystem");
 MODULE_LICENSE ("GPL");
 
 module_init(cpufreq_stats_init);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index a06c204..2a4eb0b 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -131,19 +131,26 @@
 				   unsigned int event)
 {
 	unsigned int cpu = policy->cpu;
+	int rc = 0;
+
 	switch (event) {
 	case CPUFREQ_GOV_START:
 		if (!cpu_online(cpu))
 			return -EINVAL;
 		BUG_ON(!policy->cur);
 		mutex_lock(&userspace_mutex);
+		rc = sysfs_create_file (&policy->kobj,
+					&freq_attr_scaling_setspeed.attr);
+		if (rc)
+			goto start_out;
+
 		cpu_is_managed[cpu] = 1;
 		cpu_min_freq[cpu] = policy->min;
 		cpu_max_freq[cpu] = policy->max;
 		cpu_cur_freq[cpu] = policy->cur;
 		cpu_set_freq[cpu] = policy->cur;
-		sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
+start_out:
 		mutex_unlock(&userspace_mutex);
 		break;
 	case CPUFREQ_GOV_STOP:
@@ -180,7 +187,7 @@
 		mutex_unlock(&userspace_mutex);
 		break;
 	}
-	return 0;
+	return rc;
 }
 
 
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 551f4cc..e749092 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -9,7 +9,8 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
+#define dprintk(msg...) \
+	cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
 
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
@@ -29,7 +30,8 @@
 
 			continue;
 		}
-		dprintk("table entry %u: %u kHz, %u index\n", i, freq, table[i].index);
+		dprintk("table entry %u: %u kHz, %u index\n",
+					i, freq, table[i].index);
 		if (freq < min_freq)
 			min_freq = freq;
 		if (freq > max_freq)
@@ -54,13 +56,14 @@
 	unsigned int i;
 	unsigned int count = 0;
 
-	dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
+	dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n",
+					policy->min, policy->max, policy->cpu);
 
 	if (!cpu_online(policy->cpu))
 		return -EINVAL;
 
-	cpufreq_verify_within_limits(policy,
-				     policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+				     policy->cpuinfo.max_freq);
 
 	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		unsigned int freq = table[i].frequency;
@@ -75,10 +78,11 @@
 	if (!count)
 		policy->max = next_larger;
 
-	cpufreq_verify_within_limits(policy,
-				     policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+				     policy->cpuinfo.max_freq);
 
-	dprintk("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
+	dprintk("verification lead to (%u - %u kHz) for cpu %u\n",
+				policy->min, policy->max, policy->cpu);
 
 	return 0;
 }
@@ -101,7 +105,8 @@
 	};
 	unsigned int i;
 
-	dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu);
+	dprintk("request for target %u kHz (relation: %u) for cpu %u\n",
+					target_freq, relation, policy->cpu);
 
 	switch (relation) {
 	case CPUFREQ_RELATION_H:
@@ -192,7 +197,10 @@
 }
 
 struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
-	.attr = { .name = "scaling_available_frequencies", .mode = 0444, .owner=THIS_MODULE },
+	.attr = { .name = "scaling_available_frequencies",
+		  .mode = 0444,
+		  .owner=THIS_MODULE
+		},
 	.show = show_available_freqs,
 };
 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index c034820..af02034 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -38,17 +38,6 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-algo-pca.
 
-config I2C_ALGOITE
-	tristate "ITE I2C Algorithm"
-	depends on MIPS_ITE8172 && I2C
-	help
-	  This supports the use of the ITE8172 I2C interface found on some MIPS
-	  systems. Say Y if you have one of these. You should also say Y for
-	  the ITE I2C peripheral driver support below.
-
-	  This support is also available as a module.  If so, the module 
-	  will be called i2c-algo-ite.
-
 config I2C_ALGO8XX
 	tristate "MPC8xx CPM I2C interface"
 	depends on 8xx && I2C
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
index 208be04..cac1051 100644
--- a/drivers/i2c/algos/Makefile
+++ b/drivers/i2c/algos/Makefile
@@ -5,7 +5,6 @@
 obj-$(CONFIG_I2C_ALGOBIT)	+= i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)	+= i2c-algo-pcf.o
 obj-$(CONFIG_I2C_ALGOPCA)	+= i2c-algo-pca.o
-obj-$(CONFIG_I2C_ALGOITE)	+= i2c-algo-ite.o
 obj-$(CONFIG_I2C_ALGO_SGI)	+= i2c-algo-sgi.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 21c36bf..95aa539 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -540,15 +540,7 @@
 
 	return i2c_add_adapter(adap);
 }
-
-
-int i2c_bit_del_bus(struct i2c_adapter *adap)
-{
-	return i2c_del_adapter(adap);
-}
-
 EXPORT_SYMBOL(i2c_bit_add_bus);
-EXPORT_SYMBOL(i2c_bit_del_bus);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
deleted file mode 100644
index 70d8eef..0000000
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
-   -------------------------------------------------------------------------
-   i2c-algo-ite.c i2c driver algorithms for ITE adapters	    
-   
-   Hai-Pao Fan, MontaVista Software, Inc.
-   hpfan@mvista.com or source@mvista.com
-
-   Copyright 2000 MontaVista Software Inc.
-
-   ---------------------------------------------------------------------------
-   This file was highly leveraged from i2c-algo-pcf.c, which was created
-   by Simon G. Vogl and Hans Berglund:
-
-
-     Copyright (C) 1995-1997 Simon G. Vogl
-                   1998-2000 Hans Berglund
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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.		     */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and 
-   Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
-   <mbailey@littlefeet-inc.com> */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-ite.h>
-#include "i2c-algo-ite.h"
-
-#define	PM_DSR		IT8172_PCI_IO_BASE + IT_PM_DSR
-#define	PM_IBSR		IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 
-#define GPIO_CCR	IT8172_PCI_IO_BASE + IT_GPCCR
-
-#define DEB2(x) if (i2c_debug>=2) x
-#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
-#define DEF_TIMEOUT 16
-
-
-/* module parameters:
- */
-static int i2c_debug;
-static int iic_test;	/* see if the line-setting functions work	*/
-
-/* --- setting states on the bus with the right timing: ---------------	*/
-
-#define get_clock(adap) adap->getclock(adap->data)
-#define iic_outw(adap, reg, val) adap->setiic(adap->data, reg, val)
-#define iic_inw(adap, reg) adap->getiic(adap->data, reg)
-
-
-/* --- other auxiliary functions --------------------------------------	*/
-
-static void iic_start(struct i2c_algo_iic_data *adap)
-{
-	iic_outw(adap,ITE_I2CHCR,ITE_CMD);
-}
-
-static void iic_stop(struct i2c_algo_iic_data *adap)
-{
-	iic_outw(adap,ITE_I2CHCR,0);
-	iic_outw(adap,ITE_I2CHSR,ITE_I2CHSR_TDI);
-}
-
-static void iic_reset(struct i2c_algo_iic_data *adap)
-{
-	iic_outw(adap, PM_IBSR, iic_inw(adap, PM_IBSR) | 0x80);
-}
-
-
-static int wait_for_bb(struct i2c_algo_iic_data *adap)
-{
-	int timeout = DEF_TIMEOUT;
-	short status;
-
-	status = iic_inw(adap, ITE_I2CHSR);
-#ifndef STUB_I2C
-	while (timeout-- && (status & ITE_I2CHSR_HB)) {
-		udelay(1000); /* How much is this? */
-		status = iic_inw(adap, ITE_I2CHSR);
-	}
-#endif
-	if (timeout<=0) {
-		printk(KERN_ERR "Timeout, host is busy\n");
-		iic_reset(adap);
-	}
-	return(timeout<=0);
-}
-
-/* After we issue a transaction on the IIC bus, this function
- * is called.  It puts this process to sleep until we get an interrupt from
- * from the controller telling us that the transaction we requested in complete.
- */
-static int wait_for_pin(struct i2c_algo_iic_data *adap, short *status) {
-
-	int timeout = DEF_TIMEOUT;
-	
-	timeout = wait_for_bb(adap);
-	if (timeout) {
-  		DEB2(printk("Timeout waiting for host not busy\n");)
-  		return -EIO;
-	}                           
-	timeout = DEF_TIMEOUT;
-
-	*status = iic_inw(adap, ITE_I2CHSR);
-#ifndef STUB_I2C
-	while (timeout-- && !(*status & ITE_I2CHSR_TDI)) {
-	   adap->waitforpin();
-	   *status = iic_inw(adap, ITE_I2CHSR);
-	}
-#endif
-	if (timeout <= 0)
-		return(-1);
-	else
-		return(0);
-}
-
-static int wait_for_fe(struct i2c_algo_iic_data *adap, short *status)
-{
-	int timeout = DEF_TIMEOUT;
-
-	*status = iic_inw(adap, ITE_I2CFSR);
-#ifndef STUB_I2C 
-	while (timeout-- && (*status & ITE_I2CFSR_FE)) {
-		udelay(1000);
-		iic_inw(adap, ITE_I2CFSR);
-	}
-#endif
-	if (timeout <= 0) 
-		return(-1);
-	else
-		return(0);
-}
-
-static int iic_init (struct i2c_algo_iic_data *adap)
-{
-	short i;
-
-	/* Clear bit 7 to set I2C to normal operation mode */
-	i=iic_inw(adap, PM_DSR)& 0xff7f;
-	iic_outw(adap, PM_DSR, i);
-
-	/* set IT_GPCCR port C bit 2&3 as function 2 */
-	i = iic_inw(adap, GPIO_CCR) & 0xfc0f;
-	iic_outw(adap,GPIO_CCR,i);
-
-	/* Clear slave address/sub-address */
-	iic_outw(adap,ITE_I2CSAR, 0);
-	iic_outw(adap,ITE_I2CSSAR, 0);
-
-	/* Set clock counter register */
-	iic_outw(adap,ITE_I2CCKCNT, get_clock(adap));
-
-	/* Set START/reSTART/STOP time registers */
-	iic_outw(adap,ITE_I2CSHDR, 0x0a);
-	iic_outw(adap,ITE_I2CRSUR, 0x0a);
-	iic_outw(adap,ITE_I2CPSUR, 0x0a);
-
-	/* Enable interrupts on completing the current transaction */
-	iic_outw(adap,ITE_I2CHCR, ITE_I2CHCR_IE | ITE_I2CHCR_HCE);
-
-	/* Clear transfer count */
-	iic_outw(adap,ITE_I2CFBCR, 0x0);
-
-	DEB2(printk("iic_init: Initialized IIC on ITE 0x%x\n",
-		iic_inw(adap, ITE_I2CHSR)));
-	return 0;
-}
-
-
-/*
- * Sanity check for the adapter hardware - check the reaction of
- * the bus lines only if it seems to be idle.
- */
-static int test_bus(struct i2c_algo_iic_data *adap, char *name) {
-#if 0
-	int scl,sda;
-	sda=getsda(adap);
-	if (adap->getscl==NULL) {
-		printk("test_bus: Warning: Adapter can't read from clock line - skipping test.\n");
-		return 0;		
-	}
-	scl=getscl(adap);
-	printk("test_bus: Adapter: %s scl: %d  sda: %d -- testing...\n",
-	name,getscl(adap),getsda(adap));
-	if (!scl || !sda ) {
-		printk("test_bus: %s seems to be busy.\n",adap->name);
-		goto bailout;
-	}
-	sdalo(adap);
-	printk("test_bus:1 scl: %d  sda: %d\n", getscl(adap),
-	       getsda(adap));
-	if ( 0 != getsda(adap) ) {
-		printk("test_bus: %s SDA stuck high!\n",name);
-		sdahi(adap);
-		goto bailout;
-	}
-	if ( 0 == getscl(adap) ) {
-		printk("test_bus: %s SCL unexpected low while pulling SDA low!\n",
-			name);
-		goto bailout;
-	}		
-	sdahi(adap);
-	printk("test_bus:2 scl: %d  sda: %d\n", getscl(adap),
-	       getsda(adap));
-	if ( 0 == getsda(adap) ) {
-		printk("test_bus: %s SDA stuck low!\n",name);
-		sdahi(adap);
-		goto bailout;
-	}
-	if ( 0 == getscl(adap) ) {
-		printk("test_bus: %s SCL unexpected low while SDA high!\n",
-		       adap->name);
-	goto bailout;
-	}
-	scllo(adap);
-	printk("test_bus:3 scl: %d  sda: %d\n", getscl(adap),
-	       getsda(adap));
-	if ( 0 != getscl(adap) ) {
-
-		sclhi(adap);
-		goto bailout;
-	}
-	if ( 0 == getsda(adap) ) {
-		printk("test_bus: %s SDA unexpected low while pulling SCL low!\n",
-			name);
-		goto bailout;
-	}
-	sclhi(adap);
-	printk("test_bus:4 scl: %d  sda: %d\n", getscl(adap),
-	       getsda(adap));
-	if ( 0 == getscl(adap) ) {
-		printk("test_bus: %s SCL stuck low!\n",name);
-		sclhi(adap);
-		goto bailout;
-	}
-	if ( 0 == getsda(adap) ) {
-		printk("test_bus: %s SDA unexpected low while SCL high!\n",
-			name);
-		goto bailout;
-	}
-	printk("test_bus: %s passed test.\n",name);
-	return 0;
-bailout:
-	sdahi(adap);
-	sclhi(adap);
-	return -ENODEV;
-#endif
-	return (0);
-}
-
-/* ----- Utility functions
- */
-
-
-/* Verify the device we want to talk to on the IIC bus really exists. */
-static inline int try_address(struct i2c_algo_iic_data *adap,
-		       unsigned int addr, int retries)
-{
-	int i, ret = -1;
-	short status;
-
-	for (i=0;i<retries;i++) {
-		iic_outw(adap, ITE_I2CSAR, addr);
-		iic_start(adap);
-		if (wait_for_pin(adap, &status) == 0) {
-			if ((status & ITE_I2CHSR_DNE) == 0) { 
-				iic_stop(adap);
-				iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
-				ret=1;
-				break;	/* success! */
-			}
-		}
-		iic_stop(adap);
-		udelay(adap->udelay);
-	}
-	DEB2(if (i) printk("try_address: needed %d retries for 0x%x\n",i,
-	                   addr));
-	return ret;
-}
-
-
-static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,
-                         int count)
-{
-	struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
-	int wrcount=0, timeout;
-	short status;
-	int loops, remainder, i, j;
-	union {
-		char byte[2];
-		unsigned short word;
-	} tmp;
-   
-	iic_outw(adap, ITE_I2CSSAR, (unsigned short)buf[wrcount++]);
-	count--;
-	if (count == 0)
-		return -EIO;
-
-	loops =  count / 32;		/* 32-byte FIFO */
-	remainder = count % 32;
-
-	if(loops) {
-		for(i=0; i<loops; i++) {
-
-			iic_outw(adap, ITE_I2CFBCR, 32);
-			for(j=0; j<32/2; j++) {
-				tmp.byte[1] = buf[wrcount++];
-				tmp.byte[0] = buf[wrcount++];
-				iic_outw(adap, ITE_I2CFDR, tmp.word); 
-			}
-
-			/* status FIFO overrun */
-			iic_inw(adap, ITE_I2CFSR);
-			iic_inw(adap, ITE_I2CFBCR);
-
-			iic_outw(adap, ITE_I2CHCR, ITE_WRITE);	/* Issue WRITE command */
-
-			/* Wait for transmission to complete */
-			timeout = wait_for_pin(adap, &status);
-			if(timeout) {
-				iic_stop(adap);
-				printk("iic_sendbytes: %s write timeout.\n", i2c_adap->name);
-				return -EREMOTEIO; /* got a better one ?? */
-     	}
-			if (status & ITE_I2CHSR_DB) {
-				iic_stop(adap);
-				printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name);
-				return -EREMOTEIO; /* got a better one ?? */
-			}
-		}
-	}
-	if(remainder) {
-		iic_outw(adap, ITE_I2CFBCR, remainder);
-		for(i=0; i<remainder/2; i++) {
-			tmp.byte[1] = buf[wrcount++];
-			tmp.byte[0] = buf[wrcount++];
-			iic_outw(adap, ITE_I2CFDR, tmp.word);
-		}
-
-		/* status FIFO overrun */
-		iic_inw(adap, ITE_I2CFSR);
-		iic_inw(adap, ITE_I2CFBCR);
-
-		iic_outw(adap, ITE_I2CHCR, ITE_WRITE);  /* Issue WRITE command */
-
-		timeout = wait_for_pin(adap, &status);
-		if(timeout) {
-			iic_stop(adap);
-			printk("iic_sendbytes: %s write timeout.\n", i2c_adap->name);
-			return -EREMOTEIO; /* got a better one ?? */
-		}
-#ifndef STUB_I2C
-		if (status & ITE_I2CHSR_DB) { 
-			iic_stop(adap);
-			printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name);
-			return -EREMOTEIO; /* got a better one ?? */
-		}
-#endif
-	}
-	iic_stop(adap);
-	return wrcount;
-}
-
-
-static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count,
-	int sread)
-{
-	int rdcount=0, i, timeout;
-	short status;
-	struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
-	int loops, remainder, j;
-	union {
-		char byte[2];
-		unsigned short word;
-	} tmp;
-		
-	loops = count / 32;				/* 32-byte FIFO */
-	remainder = count % 32;
-
-	if(loops) {
-		for(i=0; i<loops; i++) {
-			iic_outw(adap, ITE_I2CFBCR, 32);
-			if (sread)
-				iic_outw(adap, ITE_I2CHCR, ITE_SREAD);
-			else
-				iic_outw(adap, ITE_I2CHCR, ITE_READ);		/* Issue READ command */
-
-			timeout = wait_for_pin(adap, &status);
-			if(timeout) {
-				iic_stop(adap);
-				printk("iic_readbytes:  %s read timeout.\n", i2c_adap->name);
-				return (-1);
-			}
-#ifndef STUB_I2C
-			if (status & ITE_I2CHSR_DB) {
-				iic_stop(adap);
-				printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name);
-				return (-1);
-			}
-#endif
-
-			timeout = wait_for_fe(adap, &status);
-			if(timeout) {
-				iic_stop(adap);
-				printk("iic_readbytes:  %s FIFO is empty\n", i2c_adap->name);
-				return (-1); 
-			}
-
-			for(j=0; j<32/2; j++) {
-				tmp.word = iic_inw(adap, ITE_I2CFDR);
-				buf[rdcount++] = tmp.byte[1];
-				buf[rdcount++] = tmp.byte[0];
-			}
-
-			/* status FIFO underrun */
-			iic_inw(adap, ITE_I2CFSR);
-
-		}
-	}
-
-
-	if(remainder) {
-		remainder=(remainder+1)/2 * 2;
-		iic_outw(adap, ITE_I2CFBCR, remainder);
-		if (sread)
-			iic_outw(adap, ITE_I2CHCR, ITE_SREAD);
-		else
-		iic_outw(adap, ITE_I2CHCR, ITE_READ);		/* Issue READ command */
-
-		timeout = wait_for_pin(adap, &status);
-		if(timeout) {
-			iic_stop(adap);
-			printk("iic_readbytes:  %s read timeout.\n", i2c_adap->name);
-			return (-1);
-		}
-#ifndef STUB_I2C
-		if (status & ITE_I2CHSR_DB) {
-			iic_stop(adap);
-			printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name);
-			return (-1);
-		}
-#endif
-		timeout = wait_for_fe(adap, &status);
-		if(timeout) {
-			iic_stop(adap);
-			printk("iic_readbytes:  %s FIFO is empty\n", i2c_adap->name);
-			return (-1);
-		}         
-
-		for(i=0; i<(remainder+1)/2; i++) {
-			tmp.word = iic_inw(adap, ITE_I2CFDR);
-			buf[rdcount++] = tmp.byte[1];
-			buf[rdcount++] = tmp.byte[0];
-		}
-
-		/* status FIFO underrun */
-		iic_inw(adap, ITE_I2CFSR);
-
-	}
-
-	iic_stop(adap);
-	return rdcount;
-}
-
-
-/* This function implements combined transactions.  Combined
- * transactions consist of combinations of reading and writing blocks of data.
- * Each transfer (i.e. a read or a write) is separated by a repeated start
- * condition.
- */
-#if 0
-static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) 
-{
-   int i;
-   struct i2c_msg *pmsg;
-   int ret;
-
-   DEB2(printk("Beginning combined transaction\n"));
-
-   for(i=0; i<(num-1); i++) {
-      pmsg = &msgs[i];
-      if(pmsg->flags & I2C_M_RD) {
-         DEB2(printk("  This one is a read\n"));
-         ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER);
-      }
-      else if(!(pmsg->flags & I2C_M_RD)) {
-         DEB2(printk("This one is a write\n"));
-         ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER);
-      }
-   }
-   /* Last read or write segment needs to be terminated with a stop */
-   pmsg = &msgs[i];
-
-   if(pmsg->flags & I2C_M_RD) {
-      DEB2(printk("Doing the last read\n"));
-      ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
-   }
-   else if(!(pmsg->flags & I2C_M_RD)) {
-      DEB2(printk("Doing the last write\n"));
-      ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
-   }
-
-   return ret;
-}
-#endif
-
-
-/* Whenever we initiate a transaction, the first byte clocked
- * onto the bus after the start condition is the address (7 bit) of the
- * device we want to talk to.  This function manipulates the address specified
- * so that it makes sense to the hardware when written to the IIC peripheral.
- *
- * Note: 10 bit addresses are not supported in this driver, although they are
- * supported by the hardware.  This functionality needs to be implemented.
- */
-static inline int iic_doAddress(struct i2c_algo_iic_data *adap,
-                                struct i2c_msg *msg, int retries) 
-{
-	unsigned short flags = msg->flags;
-	unsigned int addr;
-	int ret;
-
-/* Ten bit addresses not supported right now */
-	if ( (flags & I2C_M_TEN)  ) { 
-#if 0
-		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
-		DEB2(printk("addr0: %d\n",addr));
-		ret = try_address(adap, addr, retries);
-		if (ret!=1) {
-			printk("iic_doAddress: died at extended address code.\n");
-			return -EREMOTEIO;
-		}
-		iic_outw(adap,msg->addr & 0x7f);
-		if (ret != 1) {
-			printk("iic_doAddress: died at 2nd address code.\n");
-			return -EREMOTEIO;
-		}
-		if ( flags & I2C_M_RD ) {
-			i2c_repstart(adap);
-			addr |= 0x01;
-			ret = try_address(adap, addr, retries);
-			if (ret!=1) {
-				printk("iic_doAddress: died at extended address code.\n");
-				return -EREMOTEIO;
-			}
-		}
-#endif
-	} else {
-
-		addr = ( msg->addr << 1 );
-
-#if 0
-		if (flags & I2C_M_RD )
-			addr |= 1;
-		if (flags & I2C_M_REV_DIR_ADDR )
-			addr ^= 1;
-#endif
-
-		if (iic_inw(adap, ITE_I2CSAR) != addr) {
-			iic_outw(adap, ITE_I2CSAR, addr);
-			ret = try_address(adap, addr, retries);
-			if (ret!=1) {
-				printk("iic_doAddress: died at address code.\n");
-				return -EREMOTEIO;
-			}
-		}
-
-  }
-
-	return 0;
-}
-
-
-/* Description: Prepares the controller for a transaction (clearing status
- * registers, data buffers, etc), and then calls either iic_readbytes or
- * iic_sendbytes to do the actual transaction.
- *
- * still to be done: Before we issue a transaction, we should
- * verify that the bus is not busy or in some unknown state.
- */
-static int iic_xfer(struct i2c_adapter *i2c_adap,
-		    struct i2c_msg *msgs, 
-		    int num)
-{
-	struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
-	struct i2c_msg *pmsg;
-	int i = 0;
-	int ret, timeout;
-    
-	pmsg = &msgs[i];
-
-	if(!pmsg->len) {
-		DEB2(printk("iic_xfer: read/write length is 0\n");)
-		return -EIO;
-	}
-	if(!(pmsg->flags & I2C_M_RD) && (!(pmsg->len)%2) ) {
-		DEB2(printk("iic_xfer: write buffer length is not odd\n");)
-		return -EIO; 
-	}
-
-	/* Wait for any pending transfers to complete */
-	timeout = wait_for_bb(adap);
-	if (timeout) {
-		DEB2(printk("iic_xfer: Timeout waiting for host not busy\n");)
-		return -EIO;
-	}
-
-	/* Flush FIFO */
-	iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
-
-	/* Load address */
-	ret = iic_doAddress(adap, pmsg, i2c_adap->retries);
-	if (ret)
-		return -EIO;
-
-#if 0
-	/* Combined transaction (read and write) */
-	if(num > 1) {
-           DEB2(printk("iic_xfer: Call combined transaction\n"));
-           ret = iic_combined_transaction(i2c_adap, msgs, num);
-  }
-#endif
-
-	DEB3(printk("iic_xfer: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
-		i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
-
-	if(pmsg->flags & I2C_M_RD) 		/* Read */
-		ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, 0);
-	else {													/* Write */ 
-		udelay(1000);
-		ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len);
-	}
-
-	if (ret != pmsg->len)
-		DEB3(printk("iic_xfer: error or fail on read/write %d bytes.\n",ret)); 
-	else
-		DEB3(printk("iic_xfer: read/write %d bytes.\n",ret));
-
-	return ret;
-}
-
-
-/* Implements device specific ioctls.  Higher level ioctls can
- * be found in i2c-core.c and are typical of any i2c controller (specifying
- * slave address, timeouts, etc).  These ioctls take advantage of any hardware
- * features built into the controller for which this algorithm-adapter set
- * was written.  These ioctls allow you to take control of the data and clock
- * lines and set the either high or low,
- * similar to a GPIO pin.
- */
-static int algo_control(struct i2c_adapter *adapter, 
-	unsigned int cmd, unsigned long arg)
-{
-
-  struct i2c_algo_iic_data *adap = adapter->algo_data;
-  struct i2c_iic_msg s_msg;
-  char *buf;
-	int ret;
-
-  if (cmd == I2C_SREAD) {
-		if(copy_from_user(&s_msg, (struct i2c_iic_msg *)arg, 
-				sizeof(struct i2c_iic_msg))) 
-			return -EFAULT;
-		buf = kmalloc(s_msg.len, GFP_KERNEL);
-		if (buf== NULL)
-			return -ENOMEM;
-
-		/* Flush FIFO */
-		iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
-
-		/* Load address */
-		iic_outw(adap, ITE_I2CSAR,s_msg.addr<<1);
-		iic_outw(adap, ITE_I2CSSAR,s_msg.waddr & 0xff);
-
-		ret = iic_readbytes(adapter, buf, s_msg.len, 1);
-		if (ret>=0) {
-			if(copy_to_user( s_msg.buf, buf, s_msg.len) ) 
-				ret = -EFAULT;
-		}
-		kfree(buf);
-	}
-	return 0;
-}
-
-
-static u32 iic_func(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
-	       I2C_FUNC_PROTOCOL_MANGLING; 
-}
-
-/* -----exported algorithm data: -------------------------------------	*/
-
-static struct i2c_algorithm iic_algo = {
-	.master_xfer	= iic_xfer,
-	.algo_control	= algo_control, /* ioctl */
-	.functionality	= iic_func,
-};
-
-
-/* 
- * registering functions to load algorithms at runtime 
- */
-int i2c_iic_add_bus(struct i2c_adapter *adap)
-{
-	struct i2c_algo_iic_data *iic_adap = adap->algo_data;
-
-	if (iic_test) {
-		int ret = test_bus(iic_adap, adap->name);
-		if (ret<0)
-			return -ENODEV;
-	}
-
-	DEB2(printk("i2c-algo-ite: hw routines for %s registered.\n",
-	            adap->name));
-
-	/* register new adapter to i2c module... */
-	adap->algo = &iic_algo;
-
-	adap->timeout = 100;	/* default values, should	*/
-	adap->retries = 3;		/* be replaced by defines	*/
-	adap->flags = 0;
-
-	iic_init(iic_adap);
-	return i2c_add_adapter(adap);
-}
-
-
-int i2c_iic_del_bus(struct i2c_adapter *adap)
-{
-	int res;
-	if ((res = i2c_del_adapter(adap)) < 0)
-		return res;
-	DEB2(printk("i2c-algo-ite: adapter unregistered: %s\n",adap->name));
-
-	return 0;
-}
-
-
-int __init i2c_algo_iic_init (void)
-{
-	printk(KERN_INFO "ITE iic (i2c) algorithm module\n");
-	return 0;
-}
-
-
-void i2c_algo_iic_exit(void)
-{
-	return;
-}
-
-
-EXPORT_SYMBOL(i2c_iic_add_bus);
-EXPORT_SYMBOL(i2c_iic_del_bus);
-
-/* The MODULE_* macros resolve to nothing if MODULES is not defined
- * when this file is compiled.
- */
-MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
-MODULE_DESCRIPTION("ITE iic algorithm");
-MODULE_LICENSE("GPL");
-
-module_param(iic_test, bool, 0);
-module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
-MODULE_PARM_DESC(i2c_debug,
-        "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
-
-
-/* This function resolves to init_module (the function invoked when a module
- * is loaded via insmod) when this file is compiled with MODULES defined.
- * Otherwise (i.e. if you want this driver statically linked to the kernel),
- * a pointer to this function is stored in a table and called
- * during the initialization of the kernel (in do_basic_setup in /init/main.c) 
- *
- * All this functionality is complements of the macros defined in linux/init.h
- */
-module_init(i2c_algo_iic_init);
-
-
-/* If MODULES is defined when this file is compiled, then this function will
- * resolved to cleanup_module.
- */
-module_exit(i2c_algo_iic_exit);
diff --git a/drivers/i2c/algos/i2c-algo-ite.h b/drivers/i2c/algos/i2c-algo-ite.h
deleted file mode 100644
index a8ca3c9..0000000
--- a/drivers/i2c/algos/i2c-algo-ite.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-   --------------------------------------------------------------------
-   i2c-ite.h: Global defines for the I2C controller on board the    
-                 ITE MIPS processor.                                
-   --------------------------------------------------------------------
-   Hai-Pao Fan, MontaVista Software, Inc.
-   hpfan@mvista.com or source@mvista.com
-
-   Copyright 2001 MontaVista Software Inc.
-
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef I2C_ITE_H
-#define I2C_ITE_H 1
-
-#include <asm/it8172/it8172.h>
-
-/* I2C Registers */
-#define ITE_I2CHCR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x30
-#define ITE_I2CHSR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x34
-#define ITE_I2CSAR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x38
-#define ITE_I2CSSAR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x3c
-#define ITE_I2CCKCNT	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x48
-#define ITE_I2CSHDR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x4c
-#define ITE_I2CRSUR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x50
-#define ITE_I2CPSUR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x54
-
-#define ITE_I2CFDR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x70
-#define ITE_I2CFBCR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x74
-#define ITE_I2CFCR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x78
-#define ITE_I2CFSR	IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x7c
-
-
-/* Host Control Register ITE_I2CHCR */
-#define	ITE_I2CHCR_HCE	0x01	/* Enable I2C Host Controller */
-#define	ITE_I2CHCR_IE	0x02	/* Enable the interrupt after completing
-				   the current transaction */
-#define ITE_I2CHCR_CP_W	0x00	/* bit2-4 000 - Write */
-#define	ITE_I2CHCR_CP_R	0x08	/*	  010 - Current address read */
-#define	ITE_I2CHCR_CP_S	0x10	/*	  100 - Sequential read */
-#define ITE_I2CHCR_ST	0x20	/* Initiates the I2C host controller to execute
-				   the command and send the data programmed in
-				   all required registers to I2C bus */
-#define ITE_CMD		ITE_I2CHCR_HCE | ITE_I2CHCR_IE | ITE_I2CHCR_ST
-#define ITE_WRITE	ITE_CMD | ITE_I2CHCR_CP_W
-#define ITE_READ	ITE_CMD | ITE_I2CHCR_CP_R
-#define ITE_SREAD	ITE_CMD | ITE_I2CHCR_CP_S
-
-/* Host Status Register ITE_I2CHSR */
-#define	ITE_I2CHSR_DB	0x01	/* Device is busy, receives NACK response except
-				   in the first and last bytes */
-#define	ITE_I2CHSR_DNE	0x02	/* Target address on I2C bus does not exist */
-#define	ITE_I2CHSR_TDI	0x04	/* R/W Transaction on I2C bus was completed */
-#define	ITE_I2CHSR_HB	0x08	/* Host controller is processing transactions */
-#define	ITE_I2CHSR_FER	0x10	/* Error occurs in the FIFO */
-
-/* Slave Address Register ITE_I2CSAR */
-#define	ITE_I2CSAR_SA_MASK	0xfe	/* Target I2C device address */
-#define	ITE_I2CSAR_ASO		0x0100	/* Output 1/0 to I2CAS port when the
-					   next slave address is addressed */
-
-/* Slave Sub-address Register ITE_I2CSSAR */
-#define	ITE_I2CSSAR_SUBA_MASK	0xff	/* Target I2C device sub-address */
-
-/* Clock Counter Register ITE_I2CCKCNT */
-#define	ITE_I2CCKCNT_STOP	0x00	/* stop I2C clock */
-#define	ITE_I2CCKCNT_HPCC_MASK	0x7f	/* SCL high period counter */
-#define	ITE_I2CCKCNT_LPCC_MASK	0x7f00	/* SCL low period counter */
-
-/* START Hold Time Register ITE_I2CSHDR */
-/* value is counted based on 16 MHz internal clock */
-#define ITE_I2CSHDR_FM	0x0a	/* START condition at fast mode */
-#define	ITE_I2CSHDR_SM	0x47	/* START contition at standard mode */
-
-/* (Repeated) START Setup Time Register ITE_I2CRSUR */
-/* value is counted based on 16 MHz internal clock */
-#define	ITE_I2CRSUR_FM	0x0a	/* repeated START condition at fast mode */
-#define	ITE_I2CRSUR_SM	0x50	/* repeated START condition at standard mode */
-
-/* STOP setup Time Register ITE_I2CPSUR */
-
-/* FIFO Data Register ITE_I2CFDR */
-#define	ITE_I2CFDR_MASK		0xff
-
-/* FIFO Byte Count Register ITE_I2CFBCR */
-#define ITE_I2CFBCR_MASK	0x3f
-
-/* FIFO Control Register ITE_I2CFCR */
-#define	ITE_I2CFCR_FLUSH	0x01	/* Flush FIFO and reset the FIFO point
-					   and I2CFSR */
-/* FIFO Status Register ITE_I2CFSR */
-#define	ITE_I2CFSR_FO	0x01	/* FIFO is overrun when write */
-#define	ITE_I2CFSR_FU	0x02	/* FIFO is underrun when read */
-#define	ITE_I2CFSR_FF	0x04	/* FIFO is full when write */
-#define	ITE_I2CFSR_FE	0x08	/* FIFO is empty when read */
-
-#endif  /* I2C_ITE_H */
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 9081c9f..36fdf97 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -381,14 +381,7 @@
 
 	return rval;
 }
-
-int i2c_pca_del_bus(struct i2c_adapter *adap)
-{
-	return i2c_del_adapter(adap);
-}
-
 EXPORT_SYMBOL(i2c_pca_add_bus);
-EXPORT_SYMBOL(i2c_pca_del_bus);
 
 MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
 MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 3b20033..ecb2c2d 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -486,15 +486,7 @@
 
 	return rval;
 }
-
-
-int i2c_pcf_del_bus(struct i2c_adapter *adap)
-{
-	return i2c_del_adapter(adap);
-}
-
 EXPORT_SYMBOL(i2c_pcf_add_bus);
-EXPORT_SYMBOL(i2c_pcf_del_bus);
 
 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
 MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index 490d999..ac2d505 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -171,15 +171,7 @@
 
 	return i2c_add_adapter(adap);
 }
-
-
-int i2c_sgi_del_bus(struct i2c_adapter *adap)
-{
-	return i2c_del_adapter(adap);
-}
-
 EXPORT_SYMBOL(i2c_sgi_add_bus);
-EXPORT_SYMBOL(i2c_sgi_del_bus);
 
 MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
 MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 90f91d03..e1989f3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -74,6 +74,13 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-amd8111.
 
+config I2C_AT91
+	tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
+	depends on I2C && ARCH_AT91 && EXPERIMENTAL
+	help
+	  This supports the use of the I2C interface on Atmel AT91
+	  processors.
+
 config I2C_AU1550
 	tristate "Au1550/Au1200 SMBus interface"
 	depends on I2C && (SOC_AU1550 || SOC_AU1200)
@@ -209,18 +216,6 @@
 	tristate
 	depends on I2C
 
-config I2C_ITE
-	tristate "ITE I2C Adapter"
-	depends on I2C && MIPS_ITE8172
-	select I2C_ALGOITE
-	help
-	  This supports the ITE8172 I2C peripheral found on some MIPS
-	  systems. Say Y if you have one of these. You should also say Y for
-	  the ITE I2C driver algorithm support above.
-
-	  This support is also available as a module.  If so, the module 
-	  will be called i2c-ite.
-
 config I2C_IXP4XX
 	tristate "IXP4xx GPIO-Based I2C Interface"
 	depends on I2C && ARCH_IXP4XX
@@ -481,6 +476,17 @@
 
 	  If you don't know what to do here, definitely say N.
 
+config I2C_VERSATILE
+	tristate "ARM Versatile/Realview I2C bus support"
+	depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
+	select I2C_ALGOBIT
+	help
+	  Say yes if you want to support the I2C serial bus on ARMs Versatile
+	  range of platforms.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-versatile.
+
 config I2C_VIA
 	tristate "VIA 82C586B"
 	depends on I2C && PCI && EXPERIMENTAL
@@ -548,4 +554,23 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mv64xxx.
 
+config I2C_PNX
+	tristate "I2C bus support for Philips PNX targets"
+	depends on ARCH_PNX4008 && I2C
+	help
+	  This driver supports the Philips IP3204 I2C IP block master and/or
+	  slave controller
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-pnx.
+
+config I2C_PNX_EARLY
+	bool "Early initialization for I2C on PNXxxxx"
+	depends on I2C_PNX=y
+	help
+	  Under certain circumstances one may need to make sure I2C on PNXxxxx
+	  is initialized earlier than some other driver that depends on it
+	  (for instance, that might be USB in case of PNX4008). With this
+	  option turned on you can guarantee that.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 493c872..37196c1 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD756_S4882)	+= i2c-amd756-s4882.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
+obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
 obj-$(CONFIG_I2C_HYDRA)		+= i2c-hydra.o
@@ -16,7 +17,6 @@
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_ISA)		+= i2c-isa.o
-obj-$(CONFIG_I2C_ITE)		+= i2c-ite.o
 obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
 obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
@@ -29,6 +29,7 @@
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
+obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
 obj-$(CONFIG_I2C_PROSAVAGE)	+= i2c-prosavage.o
 obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
 obj-$(CONFIG_I2C_RPXLITE)	+= i2c-rpx.o
@@ -39,6 +40,7 @@
 obj-$(CONFIG_I2C_SIS630)	+= i2c-sis630.o
 obj-$(CONFIG_I2C_SIS96X)	+= i2c-sis96x.o
 obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
+obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_VIA)		+= i2c-via.o
 obj-$(CONFIG_I2C_VIAPRO)	+= i2c-viapro.o
 obj-$(CONFIG_I2C_VOODOO3)	+= i2c-voodoo3.o
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
new file mode 100644
index 0000000..67f91bd
--- /dev/null
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -0,0 +1,325 @@
+/*
+    i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
+
+    Copyright (C) 2004 Rick Bronson
+    Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
+
+    Borrowed heavily from original work by:
+    Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.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/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/at91_twi.h>
+#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+
+#define TWI_CLOCK		100000		/* Hz. max 400 Kbits/sec */
+
+
+static struct clk *twi_clk;
+static void __iomem *twi_base;
+
+#define at91_twi_read(reg)		__raw_readl(twi_base + (reg))
+#define at91_twi_write(reg, val)	__raw_writel((val), twi_base + (reg))
+
+
+/*
+ * Initialize the TWI hardware registers.
+ */
+static void __devinit at91_twi_hwinit(void)
+{
+	unsigned long cdiv, ckdiv;
+
+	at91_twi_write(AT91_TWI_IDR, 0xffffffff);	/* Disable all interrupts */
+	at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST);	/* Reset peripheral */
+	at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN);	/* Set Master mode */
+
+	/* Calcuate clock dividers */
+	cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
+	cdiv = cdiv + 1;	/* round up */
+	ckdiv = 0;
+	while (cdiv > 255) {
+		ckdiv++;
+		cdiv = cdiv >> 1;
+	}
+
+	if (cpu_is_at91rm9200()) {			/* AT91RM9200 Errata #22 */
+		if (ckdiv > 5) {
+			printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
+			ckdiv = 5;
+		}
+	}
+
+	at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
+}
+
+/*
+ * Poll the i2c status register until the specified bit is set.
+ * Returns 0 if timed out (100 msec).
+ */
+static short at91_poll_status(unsigned long bit)
+{
+	int loop_cntr = 10000;
+
+	do {
+		udelay(10);
+	} while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
+
+	return (loop_cntr > 0);
+}
+
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+	/* Send Start */
+	at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
+
+	/* Read data */
+	while (length--) {
+		if (!length)	/* need to send Stop before reading last byte */
+			at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
+		if (!at91_poll_status(AT91_TWI_RXRDY)) {
+			dev_dbg(&adap->dev, "RXRDY timeout\n");
+			return -ETIMEDOUT;
+		}
+		*buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
+	}
+
+	return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+	/* Load first byte into transmitter */
+	at91_twi_write(AT91_TWI_THR, *buf++);
+
+	/* Send Start */
+	at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
+
+	do {
+		if (!at91_poll_status(AT91_TWI_TXRDY)) {
+			dev_dbg(&adap->dev, "TXRDY timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		length--;	/* byte was transmitted */
+
+		if (length > 0)		/* more data to send? */
+			at91_twi_write(AT91_TWI_THR, *buf++);
+	} while (length);
+
+	/* Send Stop */
+	at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
+
+	return 0;
+}
+
+/*
+ * Generic i2c master transfer entrypoint.
+ *
+ * Note: We do not use Atmel's feature of storing the "internal device address".
+ * Instead the "internal device address" has to be written using a seperate
+ * i2c message.
+ * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
+ */
+static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
+{
+	int i, ret;
+
+	dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
+
+	for (i = 0; i < num; i++) {
+		dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+			pmsg->flags & I2C_M_RD ? "read" : "writ",
+			pmsg->len, pmsg->len > 1 ? "s" : "",
+			pmsg->flags & I2C_M_RD ? "from" : "to",	pmsg->addr);
+
+		at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
+			| ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
+
+		if (pmsg->len && pmsg->buf) {	/* sanity check */
+			if (pmsg->flags & I2C_M_RD)
+				ret = xfer_read(adap, pmsg->buf, pmsg->len);
+			else
+				ret = xfer_write(adap, pmsg->buf, pmsg->len);
+
+			if (ret)
+				return ret;
+
+			/* Wait until transfer is finished */
+			if (!at91_poll_status(AT91_TWI_TXCOMP)) {
+				dev_dbg(&adap->dev, "TXCOMP timeout\n");
+				return -ETIMEDOUT;
+			}
+		}
+		dev_dbg(&adap->dev, "transfer complete\n");
+		pmsg++;		/* next message */
+	}
+	return i;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 at91_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm at91_algorithm = {
+	.master_xfer	= at91_xfer,
+	.functionality	= at91_func,
+};
+
+/*
+ * Main initialization routine.
+ */
+static int __devinit at91_i2c_probe(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter;
+	struct resource *res;
+	int rc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	if (!request_mem_region(res->start, res->end - res->start + 1, "at91_i2c"))
+		return -EBUSY;
+
+	twi_base = ioremap(res->start, res->end - res->start + 1);
+	if (!twi_base) {
+		rc = -ENOMEM;
+		goto fail0;
+	}
+
+	twi_clk = clk_get(NULL, "twi_clk");
+	if (IS_ERR(twi_clk)) {
+		dev_err(&pdev->dev, "no clock defined\n");
+		rc = -ENODEV;
+		goto fail1;
+	}
+
+	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (adapter == NULL) {
+		dev_err(&pdev->dev, "can't allocate inteface!\n");
+		rc = -ENOMEM;
+		goto fail2;
+	}
+	sprintf(adapter->name, "AT91");
+	adapter->algo = &at91_algorithm;
+	adapter->class = I2C_CLASS_HWMON;
+	adapter->dev.parent = &pdev->dev;
+
+	platform_set_drvdata(pdev, adapter);
+
+	clk_enable(twi_clk);		/* enable peripheral clock */
+	at91_twi_hwinit();		/* initialize TWI controller */
+
+	rc = i2c_add_adapter(adapter);
+	if (rc) {
+		dev_err(&pdev->dev, "Adapter %s registration failed\n",
+				adapter->name);
+		goto fail3;
+	}
+
+	dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
+	return 0;
+
+fail3:
+	platform_set_drvdata(pdev, NULL);
+	kfree(adapter);
+	clk_disable(twi_clk);
+fail2:
+	clk_put(twi_clk);
+fail1:
+	iounmap(twi_base);
+fail0:
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	return rc;
+}
+
+static int __devexit at91_i2c_remove(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+	struct resource *res;
+	int rc;
+
+	rc = i2c_del_adapter(adapter);
+	platform_set_drvdata(pdev, NULL);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iounmap(twi_base);
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	clk_disable(twi_clk);		/* disable peripheral clock */
+	clk_put(twi_clk);
+
+	return rc;
+}
+
+#ifdef CONFIG_PM
+
+/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
+
+static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	clk_disable(twi_clk);
+	return 0;
+}
+
+static int at91_i2c_resume(struct platform_device *pdev)
+{
+	return clk_enable(twi_clk);
+}
+
+#else
+#define at91_i2c_suspend	NULL
+#define at91_i2c_resume		NULL
+#endif
+
+static struct platform_driver at91_i2c_driver = {
+	.probe		= at91_i2c_probe,
+	.remove		= __devexit_p(at91_i2c_remove),
+	.suspend	= at91_i2c_suspend,
+	.resume		= at91_i2c_resume,
+	.driver		= {
+		.name	= "at91_i2c",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_i2c_init(void)
+{
+	return platform_driver_register(&at91_i2c_driver);
+}
+
+static void __exit at91_i2c_exit(void)
+{
+	platform_driver_unregister(&at91_i2c_driver);
+}
+
+module_init(at91_i2c_init);
+module_exit(at91_i2c_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index a591fe6..8349674 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -293,7 +293,7 @@
 
 static void i2c_pcfisa_exit(void)
 {
-	i2c_pcf_del_bus(&pcf_isa_ops);
+	i2c_del_adapter(&pcf_isa_ops);
 
 	if (irq > 0) {
 		disable_irq(irq);
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 457d48a..9832f77 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -146,7 +146,7 @@
 static void __devexit hydra_remove(struct pci_dev *dev)
 {
 	pdregw(hydra_bit_data.data, 0);		/* clear SCLK_OE and SDAT_OE */
-	i2c_bit_del_bus(&hydra_adap);
+	i2c_del_adapter(&hydra_adap);
 	iounmap(hydra_bit_data.data);
 	release_mem_region(pci_resource_start(dev, 0)+
 			   offsetof(struct Hydra, CachePD), 4);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index c7be2fd..ae625b8 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -470,12 +470,20 @@
 	int err;
 
 	I801_dev = dev;
-	if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
-	    (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
-	    (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
+	switch (dev->device) {
+	case PCI_DEVICE_ID_INTEL_82801DB_3:
+	case PCI_DEVICE_ID_INTEL_82801EB_3:
+	case PCI_DEVICE_ID_INTEL_ESB_4:
+	case PCI_DEVICE_ID_INTEL_ICH6_16:
+	case PCI_DEVICE_ID_INTEL_ICH7_17:
+	case PCI_DEVICE_ID_INTEL_ESB2_17:
+	case PCI_DEVICE_ID_INTEL_ICH8_5:
+	case PCI_DEVICE_ID_INTEL_ICH9_6:
 		isich4 = 1;
-	else
+		break;
+	default:
 		isich4 = 0;
+	}
 
 	err = pci_enable_device(dev);
 	if (err) {
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index b66fb6b..10c98bc 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -219,14 +219,14 @@
 		return retval;
 	retval = i2c_bit_add_bus(&i810_ddc_adapter);
 	if (retval)
-		i2c_bit_del_bus(&i810_i2c_adapter);
+		i2c_del_adapter(&i810_i2c_adapter);
 	return retval;
 }
 
 static void __devexit i810_remove(struct pci_dev *dev)
 {
-	i2c_bit_del_bus(&i810_ddc_adapter);
-	i2c_bit_del_bus(&i810_i2c_adapter);
+	i2c_del_adapter(&i810_ddc_adapter);
+	i2c_del_adapter(&i810_i2c_adapter);
 	iounmap(ioaddr);
 }
 
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 781a99c..1898e99 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -680,6 +680,12 @@
 	dev->idx = ocp->def->index;
 	ocp_set_drvdata(ocp, dev);
 	
+	if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
+				"ibm_iic")) {
+		ret = -EBUSY;
+		goto fail1;
+	}
+
 	if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
 		printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
 			dev->idx);
@@ -750,6 +756,8 @@
 
 	iounmap(dev->vaddr);
 fail2:	
+	release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
+fail1:
 	ocp_set_drvdata(ocp, NULL);
 	kfree(dev);	
 	return ret;
@@ -777,6 +785,7 @@
 		    free_irq(dev->irq, dev);
 		}
 		iounmap(dev->vaddr);
+		release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
 		kfree(dev);
 	}
 }
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
deleted file mode 100644
index f7d7186..0000000
--- a/drivers/i2c/busses/i2c-ite.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
-   -------------------------------------------------------------------------
-   i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system
-   -------------------------------------------------------------------------
-   Hai-Pao Fan, MontaVista Software, Inc.
-   hpfan@mvista.com or source@mvista.com
-
-   Copyright 2001 MontaVista Software Inc.
-
-   ----------------------------------------------------------------------------
-   This file was highly leveraged from i2c-elektor.c, which was created
-   by Simon G. Vogl and Hans Berglund:
-
- 
-     Copyright (C) 1995-97 Simon G. Vogl
-                   1998-99 Hans Berglund
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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.		     */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
-   Frodo Looijaard <frodol@dds.nl> */
-
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-ite.h>
-#include <linux/i2c-adap-ite.h>
-#include "../i2c-ite.h"
-
-#define DEFAULT_BASE  0x14014030
-#define ITE_IIC_IO_SIZE	0x40
-#define DEFAULT_IRQ   0
-#define DEFAULT_CLOCK 0x1b0e	/* default 16MHz/(27+14) = 400KHz */
-#define DEFAULT_OWN   0x55
-
-static int base;
-static int irq;
-static int clock;
-static int own;
-
-static struct iic_ite gpi;
-static wait_queue_head_t iic_wait;
-static int iic_pending;
-static spinlock_t lock;
-
-/* ----- local functions ----------------------------------------------	*/
-
-static void iic_ite_setiic(void *data, int ctl, short val)
-{
-        unsigned long j = jiffies + 10;
-
-	pr_debug(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff);
-#ifdef DEBUG
-	while (time_before(jiffies, j))
-		schedule();
-#endif
-	outw(val,ctl);
-}
-
-static short iic_ite_getiic(void *data, int ctl)
-{
-	short val;
-
-	val = inw(ctl);
-	pr_debug("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff);
-	return (val);
-}
-
-/* Return our slave address.  This is the address
- * put on the I2C bus when another master on the bus wants to address us
- * as a slave
- */
-static int iic_ite_getown(void *data)
-{
-	return (gpi.iic_own);
-}
-
-
-static int iic_ite_getclock(void *data)
-{
-	return (gpi.iic_clock);
-}
-
-
-/* Put this process to sleep.  We will wake up when the
- * IIC controller interrupts.
- */
-static void iic_ite_waitforpin(void) {
-   DEFINE_WAIT(wait);
-   int timeout = 2;
-   unsigned long flags;
-
-   /* If interrupts are enabled (which they are), then put the process to
-    * sleep.  This process will be awakened by two events -- either the
-    * the IIC peripheral interrupts or the timeout expires. 
-    * If interrupts are not enabled then delay for a reasonable amount 
-    * of time and return.
-    */
-   if (gpi.iic_irq > 0) {
-	spin_lock_irqsave(&lock, flags);
-	if (iic_pending == 0) {
-		spin_unlock_irqrestore(&lock, flags);
-		prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE);
-		if (schedule_timeout(timeout*HZ)) {
-			spin_lock_irqsave(&lock, flags);
-			if (iic_pending == 1) {
-				iic_pending = 0;
-			}
-			spin_unlock_irqrestore(&lock, flags);
-		}
-		finish_wait(&iic_wait, &wait);
-	} else {
-		iic_pending = 0;
-		spin_unlock_irqrestore(&lock, flags);
-	}
-   } else {
-      udelay(100);
-   }
-}
-
-
-static irqreturn_t iic_ite_handler(int this_irq, void *dev_id)
-{
-	spin_lock(&lock);
-	iic_pending = 1;
-	spin_unlock(&lock);
-
-	wake_up_interruptible(&iic_wait);
-
-	return IRQ_HANDLED;
-}
-
-
-/* Lock the region of memory where I/O registers exist.  Request our
- * interrupt line and register its associated handler.
- */
-static int iic_hw_resrc_init(void)
-{
-	if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c"))
-		return -ENODEV;
-  
-	if (gpi.iic_irq <= 0)
-		return 0;
-
-	if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0)
-		gpi.iic_irq = 0;
-	else
-		enable_irq(gpi.iic_irq);
-
-	return 0;
-}
-
-
-static void iic_ite_release(void)
-{
-	if (gpi.iic_irq > 0) {
-		disable_irq(gpi.iic_irq);
-		free_irq(gpi.iic_irq, 0);
-	}
-	release_region(gpi.iic_base , 2);
-}
-
-/* ------------------------------------------------------------------------
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
-static struct i2c_algo_iic_data iic_ite_data = {
-	NULL,
-	iic_ite_setiic,
-	iic_ite_getiic,
-	iic_ite_getown,
-	iic_ite_getclock,
-	iic_ite_waitforpin,
-	80, 80, 100,		/*	waits, timeout */
-};
-
-static struct i2c_adapter iic_ite_ops = {
-	.owner		= THIS_MODULE,
-	.id		= I2C_HW_I_IIC,
-	.algo_data	= &iic_ite_data,
-	.name		= "ITE IIC adapter",
-};
-
-/* Called when the module is loaded.  This function starts the
- * cascade of calls up through the hierarchy of i2c modules (i.e. up to the
- *  algorithm layer and into to the core layer)
- */
-static int __init iic_ite_init(void) 
-{
-
-	struct iic_ite *piic = &gpi;
-
-	printk(KERN_INFO "Initialize ITE IIC adapter module\n");
-	if (base == 0)
-		piic->iic_base = DEFAULT_BASE;
-	else
-		piic->iic_base = base;
-
-	if (irq == 0)
-		piic->iic_irq = DEFAULT_IRQ;
-	else
-		piic->iic_irq = irq;
-
-	if (clock == 0)
-		piic->iic_clock = DEFAULT_CLOCK;
-	else
-		piic->iic_clock = clock;
-
-	if (own == 0)
-		piic->iic_own = DEFAULT_OWN;
-	else
-		piic->iic_own = own;
-
-	iic_ite_data.data = (void *)piic;
-	init_waitqueue_head(&iic_wait);
-	spin_lock_init(&lock);
-	if (iic_hw_resrc_init() == 0) {
-		if (i2c_iic_add_bus(&iic_ite_ops) < 0)
-			return -ENODEV;
-	} else {
-		return -ENODEV;
-	}
-	printk(KERN_INFO " found device at %#x irq %d.\n", 
-		piic->iic_base, piic->iic_irq);
-	return 0;
-}
-
-
-static void iic_ite_exit(void)
-{
-	i2c_iic_del_bus(&iic_ite_ops);
-        iic_ite_release();
-}
-
-/* If modules is NOT defined when this file is compiled, then the MODULE_*
- * macros will resolve to nothing
- */
-MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
-MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter");
-MODULE_LICENSE("GPL");
-
-module_param(base, int, 0);
-module_param(irq, int, 0);
-module_param(clock, int, 0);
-module_param(own, int, 0);
-
-
-/* Called when module is loaded or when kernel is initialized.
- * If MODULES is defined when this file is compiled, then this function will
- * resolve to init_module (the function called when insmod is invoked for a
- * module).  Otherwise, this function is called early in the boot, when the
- * kernel is intialized.  Check out /include/init.h to see how this works.
- */
-module_init(iic_ite_init);
-
-/* Resolves to module_cleanup when MODULES is defined. */
-module_exit(iic_ite_exit); 
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index dd3f4cd..efa3ecc 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -90,7 +90,7 @@
 
 	platform_set_drvdata(plat_dev, NULL);
 
-	i2c_bit_del_bus(&drv_data->adapter);
+	i2c_del_adapter(&drv_data->adapter);
 
 	kfree(drv_data);
 
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index 68fe863..08e89b8 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -91,7 +91,7 @@
 
 	platform_set_drvdata(plat_dev, NULL);
 
-	i2c_bit_del_bus(&drv_data->adapter);
+	i2c_del_adapter(&drv_data->adapter);
 
 	kfree(drv_data);
 
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index e0292e4..ad37c10 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -35,7 +35,7 @@
     nForce4 MCP55		0368
 
     This driver supports the 2 SMBuses that are included in the MCP of the
-    nForce2/3/4 chipsets.
+    nForce2/3/4/5xx chipsets.
 */
 
 /* Note: we assume there can only be one nForce2, with two SMBus interfaces */
@@ -52,8 +52,8 @@
 #include <asm/io.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>");
-MODULE_DESCRIPTION("nForce2 SMBus driver");
+MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@gmx.net>");
+MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");
 
 
 struct nforce2_smbus {
@@ -80,9 +80,6 @@
 #define NVIDIA_SMB_ADDR		(smbus->base + 0x02)	/* address */
 #define NVIDIA_SMB_CMD		(smbus->base + 0x03)	/* command */
 #define NVIDIA_SMB_DATA		(smbus->base + 0x04)	/* 32 data registers */
-#define NVIDIA_SMB_BCNT		(smbus->base + 0x24)	/* number of data bytes */
-#define NVIDIA_SMB_ALRM_A	(smbus->base + 0x25)	/* alarm address */
-#define NVIDIA_SMB_ALRM_D	(smbus->base + 0x26)	/* 2 bytes alarm data */
 
 #define NVIDIA_SMB_STS_DONE	0x80
 #define NVIDIA_SMB_STS_ALRM	0x40
@@ -95,40 +92,17 @@
 #define NVIDIA_SMB_PRTCL_BYTE			0x04
 #define NVIDIA_SMB_PRTCL_BYTE_DATA		0x06
 #define NVIDIA_SMB_PRTCL_WORD_DATA		0x08
-#define NVIDIA_SMB_PRTCL_BLOCK_DATA		0x0a
-#define NVIDIA_SMB_PRTCL_PROC_CALL		0x0c
-#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL	0x0d
-#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA		0x4a
 #define NVIDIA_SMB_PRTCL_PEC			0x80
 
 static struct pci_driver nforce2_driver;
 
-static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
-		       unsigned short flags, char read_write,
-		       u8 command, int size, union i2c_smbus_data *data);
-static u32 nforce2_func(struct i2c_adapter *adapter);
-
-
-static const struct i2c_algorithm smbus_algorithm = {
-	.smbus_xfer = nforce2_access,
-	.functionality = nforce2_func,
-};
-
-static struct i2c_adapter nforce2_adapter = {
-	.owner          = THIS_MODULE,
-	.class          = I2C_CLASS_HWMON,
-	.algo           = &smbus_algorithm,
-};
-
-/* Return -1 on error. See smbus.h for more information */
+/* Return -1 on error */
 static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
 		unsigned short flags, char read_write,
 		u8 command, int size, union i2c_smbus_data * data)
 {
 	struct nforce2_smbus *smbus = adap->algo_data;
 	unsigned char protocol, pec, temp;
-	unsigned char len = 0; /* to keep the compiler quiet */
-	int i;
 
 	protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
 		NVIDIA_SMB_PRTCL_WRITE;
@@ -163,35 +137,6 @@
 			protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
 			break;
 
-		case I2C_SMBUS_BLOCK_DATA:
-			outb_p(command, NVIDIA_SMB_CMD);
-			if (read_write == I2C_SMBUS_WRITE) {
-				len = min_t(u8, data->block[0], 32);
-				outb_p(len, NVIDIA_SMB_BCNT);
-				for (i = 0; i < len; i++)
-					outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
-			}
-			protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
-			break;
-
-		case I2C_SMBUS_I2C_BLOCK_DATA:
-			len = min_t(u8, data->block[0], 32);
-			outb_p(command, NVIDIA_SMB_CMD);
-			outb_p(len, NVIDIA_SMB_BCNT);
-			if (read_write == I2C_SMBUS_WRITE)
-				for (i = 0; i < len; i++)
-					outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
-			protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA;
-			break;
-
-		case I2C_SMBUS_PROC_CALL:
-			dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-			return -1;
-
-		case I2C_SMBUS_BLOCK_PROC_CALL:
-			dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
-			return -1;
-
 		default:
 			dev_err(&adap->dev, "Unsupported transaction %d\n", size);
 			return -1;
@@ -227,19 +172,8 @@
 			break;
 
 		case I2C_SMBUS_WORD_DATA:
-		/* case I2C_SMBUS_PROC_CALL: not supported */
 			data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
 			break;
-
-		case I2C_SMBUS_BLOCK_DATA:
-		/* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */
-			len = inb_p(NVIDIA_SMB_BCNT);
-			len = min_t(u8, len, 32);
-		case I2C_SMBUS_I2C_BLOCK_DATA:
-			for (i = 0; i < len; i++)
-				data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
-			data->block[0] = len;
-			break;
 	}
 
 	return 0;
@@ -250,10 +184,14 @@
 {
 	/* other functionality might be possible, but is not tested */
 	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_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
 }
 
+static struct i2c_algorithm smbus_algorithm = {
+	.smbus_xfer	= nforce2_access,
+	.functionality	= nforce2_func,
+};
+
 
 static struct pci_device_id nforce2_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
@@ -267,7 +205,6 @@
 	{ 0 }
 };
 
-
 MODULE_DEVICE_TABLE (pci, nforce2_ids);
 
 
@@ -291,7 +228,7 @@
 		}
 
 		smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
-		smbus->size = 8;
+		smbus->size = 64;
 	}
 	smbus->dev = dev;
 
@@ -300,7 +237,9 @@
 			smbus->base, smbus->base+smbus->size-1, name);
 		return -1;
 	}
-	smbus->adapter = nforce2_adapter;
+	smbus->adapter.owner = THIS_MODULE;
+	smbus->adapter.class = I2C_CLASS_HWMON;
+	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 	smbus->adapter.dev.parent = &dev->dev;
 	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index dec04da..bcd8367 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -231,8 +231,8 @@
 		 * 13		2		1
 		 * 19.2		2		1
 		 */
-		if (fclk_rate > 16000000)
-			psc = (fclk_rate + 8000000) / 12000000;
+		if (fclk_rate > 12000000)
+			psc = fclk_rate / 12000000;
 	}
 
 	/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 5eb2bd2..4bc4281 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -163,7 +163,7 @@
 	if (adapter_parm[type].init.val)
 		line_set(0, &adapter_parm[type].init);
 
-	i2c_bit_del_bus(&parport_adapter);
+	i2c_del_adapter(&parport_adapter);
 	release_region(base, 3);
 }
 
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 48a8294..66696a4 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -218,7 +218,7 @@
 			if (adapter_parm[type].init.val)
 				line_set(port, 0, &adapter_parm[type].init);
 				
-			i2c_bit_del_bus(&adapter->adapter);
+			i2c_del_adapter(&adapter->adapter);
 			parport_unregister_device(adapter->pdev);
 			if (prev)
 				prev->next = adapter->next;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 407840b..cc6536a 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -156,7 +156,7 @@
 
 static void pca_isa_exit(void)
 {
-	i2c_pca_del_bus(&pca_isa_ops);
+	i2c_del_adapter(&pca_isa_ops);
 
 	if (irq > 0) {
 		disable_irq(irq);
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
new file mode 100644
index 0000000..de0bca7
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -0,0 +1,708 @@
+/*
+ * Provides I2C support for Philips PNX010x/PNX4008 boards.
+ *
+ * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
+ *	    Vitaly Wool <vwool@ru.mvista.com>
+ *
+ * 2004-2006 (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.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/i2c-pnx.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define I2C_PNX_TIMEOUT		10 /* msec */
+#define I2C_PNX_SPEED_KHZ	100
+#define I2C_PNX_REGION_SIZE	0x100
+#define PNX_DEFAULT_FREQ	13 /* MHz */
+
+static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
+{
+	while (timeout > 0 &&
+			(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
+		mdelay(1);
+		timeout--;
+	}
+	return (timeout <= 0);
+}
+
+static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
+{
+	while (timeout > 0 &&
+			(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
+		mdelay(1);
+		timeout--;
+	}
+	return (timeout <= 0);
+}
+
+static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap)
+{
+	struct i2c_pnx_algo_data *data = adap->algo_data;
+	struct timer_list *timer = &data->mif.timer;
+	int expires = I2C_PNX_TIMEOUT / (1000 / HZ);
+
+	del_timer_sync(timer);
+
+	dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n",
+		jiffies, expires);
+
+	timer->expires = jiffies + expires;
+	timer->data = (unsigned long)adap;
+
+	add_timer(timer);
+}
+
+/**
+ * i2c_pnx_start - start a device
+ * @slave_addr:		slave address
+ * @adap:		pointer to adapter structure
+ *
+ * Generate a START signal in the desired mode.
+ */
+static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
+{
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+	dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__,
+		slave_addr, alg_data->mif.mode);
+
+	/* Check for 7 bit slave addresses only */
+	if (slave_addr & ~0x7f) {
+		dev_err(&adap->dev, "%s: Invalid slave address %x. "
+		       "Only 7-bit addresses are supported\n",
+		       adap->name, slave_addr);
+		return -EINVAL;
+	}
+
+	/* First, make sure bus is idle */
+	if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
+		/* Somebody else is monopolizing the bus */
+		dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, "
+		       "cntrl = %x, stat = %x\n",
+		       adap->name, slave_addr,
+		       ioread32(I2C_REG_CTL(alg_data)),
+		       ioread32(I2C_REG_STS(alg_data)));
+		return -EBUSY;
+	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
+		/* Sorry, we lost the bus */
+		dev_err(&adap->dev, "%s: Arbitration failure. "
+		       "Slave addr = %02x\n", adap->name, slave_addr);
+		return -EIO;
+	}
+
+	/*
+	 * OK, I2C is enabled and we have the bus.
+	 * Clear the current TDI and AFI status flags.
+	 */
+	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
+		  I2C_REG_STS(alg_data));
+
+	dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__,
+		(slave_addr << 1) | start_bit | alg_data->mif.mode);
+
+	/* Write the slave address, START bit and R/W bit */
+	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
+		  I2C_REG_TX(alg_data));
+
+	dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
+
+	return 0;
+}
+
+/**
+ * i2c_pnx_stop - stop a device
+ * @adap:		pointer to I2C adapter structure
+ *
+ * Generate a STOP signal to terminate the master transaction.
+ */
+static void i2c_pnx_stop(struct i2c_adapter *adap)
+{
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	/* Only 1 msec max timeout due to interrupt context */
+	long timeout = 1000;
+
+	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+	/* Write a STOP bit to TX FIFO */
+	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
+
+	/* Wait until the STOP is seen. */
+	while (timeout > 0 &&
+	       (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
+		/* may be called from interrupt context */
+		udelay(1);
+		timeout--;
+	}
+
+	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+}
+
+/**
+ * i2c_pnx_master_xmit - transmit data to slave
+ * @adap:		pointer to I2C adapter structure
+ *
+ * Sends one byte of data to the slave
+ */
+static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+{
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	u32 val;
+
+	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+	if (alg_data->mif.len > 0) {
+		/* We still have something to talk about... */
+		val = *alg_data->mif.buf++;
+
+		if (alg_data->mif.len == 1) {
+			val |= stop_bit;
+			if (!alg_data->last)
+				val |= start_bit;
+		}
+
+		alg_data->mif.len--;
+		iowrite32(val, I2C_REG_TX(alg_data));
+
+		dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__,
+			val, alg_data->mif.len + 1);
+
+		if (alg_data->mif.len == 0) {
+			if (alg_data->last) {
+				/* Wait until the STOP is seen. */
+				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
+					dev_err(&adap->dev, "The bus is still "
+						"active after timeout\n");
+			}
+			/* Disable master interrupts */
+			iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
+				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
+				  I2C_REG_CTL(alg_data));
+
+			del_timer_sync(&alg_data->mif.timer);
+
+			dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
+				__FUNCTION__);
+
+			complete(&alg_data->mif.complete);
+		}
+	} else if (alg_data->mif.len == 0) {
+		/* zero-sized transfer */
+		i2c_pnx_stop(adap);
+
+		/* Disable master interrupts. */
+		iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
+			~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
+			  I2C_REG_CTL(alg_data));
+
+		/* Stop timer. */
+		del_timer_sync(&alg_data->mif.timer);
+		dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
+			"zero-xfer.\n", __FUNCTION__);
+
+		complete(&alg_data->mif.complete);
+	}
+
+	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+	return 0;
+}
+
+/**
+ * i2c_pnx_master_rcv - receive data from slave
+ * @adap:		pointer to I2C adapter structure
+ *
+ * Reads one byte data from the slave
+ */
+static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+{
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	unsigned int val = 0;
+	u32 ctl = 0;
+
+	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+	/* Check, whether there is already data,
+	 * or we didn't 'ask' for it yet.
+	 */
+	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
+		dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
+			"Rx-fifo...\n", __FUNCTION__);
+
+		if (alg_data->mif.len == 1) {
+			/* Last byte, do not acknowledge next rcv. */
+			val |= stop_bit;
+			if (!alg_data->last)
+				val |= start_bit;
+
+			/*
+			 * Enable interrupt RFDAIE (data in Rx fifo),
+			 * and disable DRMIE (need data for Tx)
+			 */
+			ctl = ioread32(I2C_REG_CTL(alg_data));
+			ctl |= mcntrl_rffie | mcntrl_daie;
+			ctl &= ~mcntrl_drmie;
+			iowrite32(ctl, I2C_REG_CTL(alg_data));
+		}
+
+		/*
+		 * Now we'll 'ask' for data:
+		 * For each byte we want to receive, we must
+		 * write a (dummy) byte to the Tx-FIFO.
+		 */
+		iowrite32(val, I2C_REG_TX(alg_data));
+
+		return 0;
+	}
+
+	/* Handle data. */
+	if (alg_data->mif.len > 0) {
+		val = ioread32(I2C_REG_RX(alg_data));
+		*alg_data->mif.buf++ = (u8) (val & 0xff);
+		dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val,
+			alg_data->mif.len);
+
+		alg_data->mif.len--;
+		if (alg_data->mif.len == 0) {
+			if (alg_data->last)
+				/* Wait until the STOP is seen. */
+				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
+					dev_err(&adap->dev, "The bus is still "
+						"active after timeout\n");
+
+			/* Disable master interrupts */
+			ctl = ioread32(I2C_REG_CTL(alg_data));
+			ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
+				 mcntrl_drmie | mcntrl_daie);
+			iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+			/* Kill timer. */
+			del_timer_sync(&alg_data->mif.timer);
+			complete(&alg_data->mif.complete);
+		}
+	}
+
+	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+	return 0;
+}
+
+static irqreturn_t
+i2c_pnx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 stat, ctl;
+	struct i2c_adapter *adap = dev_id;
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+	dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
+		__FUNCTION__,
+		ioread32(I2C_REG_STS(alg_data)),
+		ioread32(I2C_REG_CTL(alg_data)),
+		alg_data->mif.mode);
+	stat = ioread32(I2C_REG_STS(alg_data));
+
+	/* let's see what kind of event this is */
+	if (stat & mstatus_afi) {
+		/* We lost arbitration in the midst of a transfer */
+		alg_data->mif.ret = -EIO;
+
+		/* Disable master interrupts. */
+		ctl = ioread32(I2C_REG_CTL(alg_data));
+		ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
+			 mcntrl_drmie);
+		iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+		/* Stop timer, to prevent timeout. */
+		del_timer_sync(&alg_data->mif.timer);
+		complete(&alg_data->mif.complete);
+	} else if (stat & mstatus_nai) {
+		/* Slave did not acknowledge, generate a STOP */
+		dev_dbg(&adap->dev, "%s(): "
+			"Slave did not acknowledge, generating a STOP.\n",
+			__FUNCTION__);
+		i2c_pnx_stop(adap);
+
+		/* Disable master interrupts. */
+		ctl = ioread32(I2C_REG_CTL(alg_data));
+		ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
+			 mcntrl_drmie);
+		iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+		/* Our return value. */
+		alg_data->mif.ret = -EIO;
+
+		/* Stop timer, to prevent timeout. */
+		del_timer_sync(&alg_data->mif.timer);
+		complete(&alg_data->mif.complete);
+	} else {
+		/*
+		 * Two options:
+		 * - Master Tx needs data.
+		 * - There is data in the Rx-fifo
+		 * The latter is only the case if we have requested for data,
+		 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
+		 * We therefore check, as a sanity check, whether that interrupt
+		 * has been enabled.
+		 */
+		if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
+			if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
+				i2c_pnx_master_xmit(adap);
+			} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
+				i2c_pnx_master_rcv(adap);
+			}
+		}
+	}
+
+	/* Clear TDI and AFI bits */
+	stat = ioread32(I2C_REG_STS(alg_data));
+	iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
+
+	dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
+		 __FUNCTION__, ioread32(I2C_REG_STS(alg_data)),
+		 ioread32(I2C_REG_CTL(alg_data)));
+
+	return IRQ_HANDLED;
+}
+
+static void i2c_pnx_timeout(unsigned long data)
+{
+	struct i2c_adapter *adap = (struct i2c_adapter *)data;
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	u32 ctl;
+
+	dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. "
+	       "Resetting master...\n",
+	       ioread32(I2C_REG_STS(alg_data)),
+	       ioread32(I2C_REG_CTL(alg_data)));
+
+	/* Reset master and disable interrupts */
+	ctl = ioread32(I2C_REG_CTL(alg_data));
+	ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
+	iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+	ctl |= mcntrl_reset;
+	iowrite32(ctl, I2C_REG_CTL(alg_data));
+	wait_reset(I2C_PNX_TIMEOUT, alg_data);
+	alg_data->mif.ret = -EIO;
+	complete(&alg_data->mif.complete);
+}
+
+static inline void bus_reset_if_active(struct i2c_adapter *adap)
+{
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	u32 stat;
+
+	if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
+		dev_err(&adap->dev,
+			"%s: Bus is still active after xfer. Reset it...\n",
+		       adap->name);
+		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
+			  I2C_REG_CTL(alg_data));
+		wait_reset(I2C_PNX_TIMEOUT, alg_data);
+	} else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
+		/* If there is data in the fifo's after transfer,
+		 * flush fifo's by reset.
+		 */
+		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
+			  I2C_REG_CTL(alg_data));
+		wait_reset(I2C_PNX_TIMEOUT, alg_data);
+	} else if (stat & mstatus_nai) {
+		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
+			  I2C_REG_CTL(alg_data));
+		wait_reset(I2C_PNX_TIMEOUT, alg_data);
+	}
+}
+
+/**
+ * i2c_pnx_xfer - generic transfer entry point
+ * @adap:		pointer to I2C adapter structure
+ * @msgs:		array of messages
+ * @num:		number of messages
+ *
+ * Initiates the transfer
+ */
+static int
+i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+	struct i2c_msg *pmsg;
+	int rc = 0, completed = 0, i;
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	u32 stat = ioread32(I2C_REG_STS(alg_data));
+
+	dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
+		__FUNCTION__, num, ioread32(I2C_REG_STS(alg_data)));
+
+	bus_reset_if_active(adap);
+
+	/* Process transactions in a loop. */
+	for (i = 0; rc >= 0 && i < num; i++) {
+		u8 addr;
+
+		pmsg = &msgs[i];
+		addr = pmsg->addr;
+
+		if (pmsg->flags & I2C_M_TEN) {
+			dev_err(&adap->dev,
+				"%s: 10 bits addr not supported!\n",
+				adap->name);
+			rc = -EINVAL;
+			break;
+		}
+
+		alg_data->mif.buf = pmsg->buf;
+		alg_data->mif.len = pmsg->len;
+		alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
+			I2C_SMBUS_READ : I2C_SMBUS_WRITE;
+		alg_data->mif.ret = 0;
+		alg_data->last = (i == num - 1);
+
+		dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__,
+			alg_data->mif.mode,
+			alg_data->mif.len);
+
+		i2c_pnx_arm_timer(adap);
+
+		/* initialize the completion var */
+		init_completion(&alg_data->mif.complete);
+
+		/* Enable master interrupt */
+		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
+				mcntrl_naie | mcntrl_drmie,
+			  I2C_REG_CTL(alg_data));
+
+		/* Put start-code and slave-address on the bus. */
+		rc = i2c_pnx_start(addr, adap);
+		if (rc < 0)
+			break;
+
+		/* Wait for completion */
+		wait_for_completion(&alg_data->mif.complete);
+
+		if (!(rc = alg_data->mif.ret))
+			completed++;
+		dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
+			__FUNCTION__, rc);
+
+		/* Clear TDI and AFI bits in case they are set. */
+		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
+			dev_dbg(&adap->dev,
+				"%s: TDI still set... clearing now.\n",
+			       adap->name);
+			iowrite32(stat, I2C_REG_STS(alg_data));
+		}
+		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
+			dev_dbg(&adap->dev,
+				"%s: AFI still set... clearing now.\n",
+			       adap->name);
+			iowrite32(stat, I2C_REG_STS(alg_data));
+		}
+	}
+
+	bus_reset_if_active(adap);
+
+	/* Cleanup to be sure... */
+	alg_data->mif.buf = NULL;
+	alg_data->mif.len = 0;
+
+	dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
+		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+	if (completed != num)
+		return ((rc < 0) ? rc : -EREMOTEIO);
+
+	return num;
+}
+
+static u32 i2c_pnx_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm pnx_algorithm = {
+	.master_xfer = i2c_pnx_xfer,
+	.functionality = i2c_pnx_func,
+};
+
+static int i2c_pnx_controller_suspend(struct platform_device *pdev,
+				      pm_message_t state)
+{
+	struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
+	return i2c_pnx->suspend(pdev, state);
+}
+
+static int i2c_pnx_controller_resume(struct platform_device *pdev)
+{
+	struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
+	return i2c_pnx->resume(pdev);
+}
+
+static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+{
+	unsigned long tmp;
+	int ret = 0;
+	struct i2c_pnx_algo_data *alg_data;
+	int freq_mhz;
+	struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
+
+	if (!i2c_pnx || !i2c_pnx->adapter) {
+		dev_err(&pdev->dev, "%s: no platform data supplied\n",
+		       __FUNCTION__);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	platform_set_drvdata(pdev, i2c_pnx);
+
+	if (i2c_pnx->calculate_input_freq)
+		freq_mhz = i2c_pnx->calculate_input_freq(pdev);
+	else {
+		freq_mhz = PNX_DEFAULT_FREQ;
+		dev_info(&pdev->dev, "Setting bus frequency to default value: "
+		       "%d MHz", freq_mhz);
+	}
+
+	i2c_pnx->adapter->algo = &pnx_algorithm;
+
+	alg_data = i2c_pnx->adapter->algo_data;
+	init_timer(&alg_data->mif.timer);
+	alg_data->mif.timer.function = i2c_pnx_timeout;
+	alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter;
+
+	/* Register I/O resource */
+	if (!request_region(alg_data->base, I2C_PNX_REGION_SIZE, pdev->name)) {
+		dev_err(&pdev->dev,
+		       "I/O region 0x%08x for I2C already in use.\n",
+		       alg_data->base);
+		ret = -ENODEV;
+		goto out_drvdata;
+	}
+
+	if (!(alg_data->ioaddr =
+			(u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) {
+		dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
+		ret = -ENOMEM;
+		goto out_release;
+	}
+
+	i2c_pnx->set_clock_run(pdev);
+
+	/*
+	 * Clock Divisor High This value is the number of system clocks
+	 * the serial clock (SCL) will be high.
+	 * For example, if the system clock period is 50 ns and the maximum
+	 * desired serial period is 10000 ns (100 kHz), then CLKHI would be
+	 * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
+	 * programmed into CLKHI will vary from this slightly due to
+	 * variations in the output pad's rise and fall times as well as
+	 * the deglitching filter length.
+	 */
+
+	tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
+	iowrite32(tmp, I2C_REG_CKH(alg_data));
+	iowrite32(tmp, I2C_REG_CKL(alg_data));
+
+	iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
+	if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
+		ret = -ENODEV;
+		goto out_unmap;
+	}
+	init_completion(&alg_data->mif.complete);
+
+	ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
+			0, pdev->name, i2c_pnx->adapter);
+	if (ret)
+		goto out_clock;
+
+	/* Register this adapter with the I2C subsystem */
+	i2c_pnx->adapter->dev.parent = &pdev->dev;
+	ret = i2c_add_adapter(i2c_pnx->adapter);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
+		goto out_irq;
+	}
+
+	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
+	       i2c_pnx->adapter->name, alg_data->base, alg_data->irq);
+
+	return 0;
+
+out_irq:
+	free_irq(alg_data->irq, alg_data);
+out_clock:
+	i2c_pnx->set_clock_stop(pdev);
+out_unmap:
+	iounmap((void *)alg_data->ioaddr);
+out_release:
+	release_region(alg_data->base, I2C_PNX_REGION_SIZE);
+out_drvdata:
+	platform_set_drvdata(pdev, NULL);
+out:
+	return ret;
+}
+
+static int __devexit i2c_pnx_remove(struct platform_device *pdev)
+{
+	struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
+	struct i2c_adapter *adap = i2c_pnx->adapter;
+	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+	free_irq(alg_data->irq, alg_data);
+	i2c_del_adapter(adap);
+	i2c_pnx->set_clock_stop(pdev);
+	iounmap((void *)alg_data->ioaddr);
+	release_region(alg_data->base, I2C_PNX_REGION_SIZE);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver i2c_pnx_driver = {
+	.driver = {
+		.name = "pnx-i2c",
+		.owner = THIS_MODULE,
+	},
+	.probe = i2c_pnx_probe,
+	.remove = __devexit_p(i2c_pnx_remove),
+	.suspend = i2c_pnx_controller_suspend,
+	.resume = i2c_pnx_controller_resume,
+};
+
+static int __init i2c_adap_pnx_init(void)
+{
+	return platform_driver_register(&i2c_pnx_driver);
+}
+
+static void __exit i2c_adap_pnx_exit(void)
+{
+	platform_driver_unregister(&i2c_pnx_driver);
+}
+
+MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
+MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
+MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_I2C_PNX_EARLY
+/* We need to make sure I2C is initialized before USB */
+subsys_initcall(i2c_adap_pnx_init);
+#else
+mudule_init(i2c_adap_pnx_init);
+#endif
+module_exit(i2c_adap_pnx_exit);
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 7745e21..07c1f1e 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -212,7 +212,7 @@
 		if (chip->i2c_bus[i].adap_ok == 0)
 			continue;
 
-		ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
+		ret = i2c_del_adapter(&chip->i2c_bus[i].adap);
 	        if (ret) {
 			dev_err(&dev->dev, "%s not removed\n",
 				chip->i2c_bus[i].adap.name);
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 209f47e..844b4ff 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -173,7 +173,7 @@
 
 static void __devexit savage4_remove(struct pci_dev *dev)
 {
-	i2c_bit_del_bus(&savage4_i2c_adapter);
+	i2c_del_adapter(&savage4_i2c_adapter);
 	iounmap(ioaddr);
 }
 
diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
new file mode 100644
index 0000000..081d957
--- /dev/null
+++ b/drivers/i2c/busses/i2c-versatile.c
@@ -0,0 +1,153 @@
+/*
+ *  i2c-versatile.c
+ *
+ *  Copyright (C) 2006 ARM Ltd.
+ *  written by Russell King, Deep Blue Solutions Ltd.
+ *
+ * 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/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#define I2C_CONTROL	0x00
+#define I2C_CONTROLS	0x00
+#define I2C_CONTROLC	0x04
+#define SCL		(1 << 0)
+#define SDA		(1 << 1)
+
+struct i2c_versatile {
+	struct i2c_adapter	 adap;
+	struct i2c_algo_bit_data algo;
+	void __iomem		 *base;
+};
+
+static void i2c_versatile_setsda(void *data, int state)
+{
+	struct i2c_versatile *i2c = data;
+
+	writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
+}
+
+static void i2c_versatile_setscl(void *data, int state)
+{
+	struct i2c_versatile *i2c = data;
+
+	writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
+}
+
+static int i2c_versatile_getsda(void *data)
+{
+	struct i2c_versatile *i2c = data;
+	return !!(readl(i2c->base + I2C_CONTROL) & SDA);
+}
+
+static int i2c_versatile_getscl(void *data)
+{
+	struct i2c_versatile *i2c = data;
+	return !!(readl(i2c->base + I2C_CONTROL) & SCL);
+}
+
+static struct i2c_algo_bit_data i2c_versatile_algo = {
+	.setsda	= i2c_versatile_setsda,
+	.setscl = i2c_versatile_setscl,
+	.getsda	= i2c_versatile_getsda,
+	.getscl = i2c_versatile_getscl,
+	.udelay	= 30,
+	.timeout = HZ,
+};
+
+static int i2c_versatile_probe(struct platform_device *dev)
+{
+	struct i2c_versatile *i2c;
+	struct resource *r;
+	int ret;
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!r) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) {
+		ret = -EBUSY;
+		goto err_out;
+	}
+
+	i2c = kzalloc(sizeof(struct i2c_versatile), GFP_KERNEL);
+	if (!i2c) {
+		ret = -ENOMEM;
+		goto err_release;
+	}
+
+	i2c->base = ioremap(r->start, r->end - r->start + 1);
+	if (!i2c->base) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	writel(SCL | SDA, i2c->base + I2C_CONTROLS);
+
+	i2c->adap.owner = THIS_MODULE;
+	strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
+	i2c->adap.algo_data = &i2c->algo;
+	i2c->adap.dev.parent = &dev->dev;
+	i2c->algo = i2c_versatile_algo;
+	i2c->algo.data = i2c;
+
+	ret = i2c_bit_add_bus(&i2c->adap);
+	if (ret >= 0) {
+		platform_set_drvdata(dev, i2c);
+		return 0;
+	}
+
+	iounmap(i2c->base);
+ err_free:
+	kfree(i2c);
+ err_release:
+	release_mem_region(r->start, r->end - r->start + 1);
+ err_out:
+	return ret;
+}
+
+static int i2c_versatile_remove(struct platform_device *dev)
+{
+	struct i2c_versatile *i2c = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+
+	i2c_del_adapter(&i2c->adap);
+	return 0;
+}
+
+static struct platform_driver i2c_versatile_driver = {
+	.probe		= i2c_versatile_probe,
+	.remove		= i2c_versatile_remove,
+	.driver		= {
+		.name	= "versatile-i2c",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init i2c_versatile_init(void)
+{
+	return platform_driver_register(&i2c_versatile_driver);
+}
+
+static void __exit i2c_versatile_exit(void)
+{
+	platform_driver_unregister(&i2c_versatile_driver);
+}
+
+module_init(i2c_versatile_init);
+module_exit(i2c_versatile_exit);
+
+MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 910e200..15d7e00 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -151,7 +151,7 @@
 
 static void __devexit vt586b_remove(struct pci_dev *dev)
 {
-	i2c_bit_del_bus(&vt586b_adapter);
+	i2c_del_adapter(&vt586b_adapter);
 	release_region(I2C_DIR, IOSPACE);
 	pm_io_base = 0;
 }
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 6c8d251..b0377b8 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -211,14 +211,14 @@
 		return retval;
 	retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
 	if (retval)
-		i2c_bit_del_bus(&voodoo3_i2c_adapter);
+		i2c_del_adapter(&voodoo3_i2c_adapter);
 	return retval;
 }
 
 static void __devexit voodoo3_remove(struct pci_dev *dev)
 {
-	i2c_bit_del_bus(&voodoo3_i2c_adapter);
- 	i2c_bit_del_bus(&voodoo3_ddc_adapter);
+	i2c_del_adapter(&voodoo3_i2c_adapter);
+	i2c_del_adapter(&voodoo3_ddc_adapter);
 	iounmap(ioaddr);
 }
 
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index 8ddbae4..6cd96e4 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -116,7 +116,7 @@
 
 static void scx200_i2c_cleanup(void)
 {
-	i2c_bit_del_bus(&scx200_i2c_ops);
+	i2c_del_adapter(&scx200_i2c_ops);
 }
 
 module_init(scx200_i2c_init);
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 93d483b..ec17d6b 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -347,13 +347,19 @@
 
 	if ((status & 0x80) || (control & 0x80)) {
 		/* RTC not running */
-		u8 buf[16];
+		u8 buf[1+16];	/* First byte is interpreted as address */
 		struct i2c_msg msg[1];
 
 		dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
 
 		/* Initialize all, including STATUS and CONTROL to zero */
 		memset(buf, 0, sizeof(buf));
+
+		/* Write valid values in the date/time registers */
+		buf[1+DS1337_REG_DAY] = 1;
+		buf[1+DS1337_REG_DATE] = 1;
+		buf[1+DS1337_REG_MONTH] = 1;
+
 		msg[0].addr = client->addr;
 		msg[0].flags = 0;
 		msg[0].len = sizeof(buf);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7ca81f42..3e31f1d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -127,20 +127,17 @@
 	return sprintf(buf, "%s\n", client->name);
 }
 
-/* 
- * We can't use the DEVICE_ATTR() macro here as we want the same filename for a
- * different type of a device.  So beware if the DEVICE_ATTR() macro ever
- * changes, this definition will also have to change.
+/*
+ * We can't use the DEVICE_ATTR() macro here, as we used the same name for
+ * an i2c adapter attribute (above).
  */
-static struct device_attribute dev_attr_client_name = {
-	.attr	= {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE },
-	.show	= &show_client_name,
-};
+static struct device_attribute dev_attr_client_name =
+	__ATTR(name, S_IRUGO, &show_client_name, NULL);
 
 
 /* ---------------------------------------------------
- * registering functions 
- * --------------------------------------------------- 
+ * registering functions
+ * ---------------------------------------------------
  */
 
 /* -----
@@ -314,7 +311,7 @@
 	res = driver_register(&driver->driver);
 	if (res)
 		return res;
-	
+
 	mutex_lock(&core_lists);
 
 	list_add_tail(&driver->list,&drivers);
@@ -338,13 +335,13 @@
 	struct list_head   *item1, *item2, *_n;
 	struct i2c_client  *client;
 	struct i2c_adapter *adap;
-	
+
 	int res = 0;
 
 	mutex_lock(&core_lists);
 
 	/* Have a look at each adapter, if clients of this driver are still
-	 * attached. If so, detach them to be able to kill the driver 
+	 * attached. If so, detach them to be able to kill the driver
 	 * afterwards.
 	 */
 	list_for_each(item1,&adapters) {
@@ -419,14 +416,14 @@
 		goto out_unlock;
 	}
 	list_add_tail(&client->list,&adapter->clients);
-	
+
 	client->usage_count = 0;
 
 	client->dev.parent = &client->adapter->dev;
 	client->dev.driver = &client->driver->driver;
 	client->dev.bus = &i2c_bus_type;
 	client->dev.release = &i2c_client_release;
-	
+
 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
 	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
@@ -467,7 +464,7 @@
 {
 	struct i2c_adapter *adapter = client->adapter;
 	int res = 0;
-	
+
 	if (client->usage_count > 0) {
 		dev_warn(&client->dev, "Client [%s] still busy, "
 			 "can't detach\n", client->name);
@@ -535,10 +532,10 @@
 			 __FUNCTION__);
 		return -EPERM;
 	}
-	
+
 	client->usage_count--;
 	i2c_dec_use_client(client);
-	
+
 	return 0;
 }
 
@@ -603,7 +600,7 @@
 		}
 #endif
 
-		mutex_lock(&adap->bus_lock);
+		mutex_lock_nested(&adap->bus_lock, adap->level);
 		ret = adap->algo->master_xfer(adap,msgs,num);
 		mutex_unlock(&adap->bus_lock);
 
@@ -624,7 +621,7 @@
 	msg.flags = client->flags & I2C_M_TEN;
 	msg.len = count;
 	msg.buf = (char *)buf;
-	
+
 	ret = i2c_transfer(adap, &msg, 1);
 
 	/* If everything went ok (i.e. 1 msg transmitted), return #bytes
@@ -757,7 +754,7 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
 		if (address_data->probe[0] == I2C_CLIENT_END
 		 && address_data->normal_i2c[0] == I2C_CLIENT_END)
-		 	return 0;
+			return 0;
 
 		dev_warn(&adapter->dev, "SMBus Quick command not supported, "
 			 "can't probe for chips\n");
@@ -817,7 +814,7 @@
 struct i2c_adapter* i2c_get_adapter(int id)
 {
 	struct i2c_adapter *adapter;
-	
+
 	mutex_lock(&core_lists);
 	adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
 	if (adapter && !try_module_get(adapter->owner))
@@ -834,14 +831,14 @@
 
 /* The SMBus parts */
 
-#define POLY    (0x1070U << 3) 
+#define POLY    (0x1070U << 3)
 static u8
 crc8(u16 data)
 {
 	int i;
-  
+
 	for(i = 0; i < 8; i++) {
-		if (data & 0x8000) 
+		if (data & 0x8000)
 			data = data ^ POLY;
 		data = data << 1;
 	}
@@ -891,13 +888,13 @@
 			rpec, cpec);
 		return -1;
 	}
-	return 0;	
+	return 0;
 }
 
 s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
 {
 	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- 	                      value,0,I2C_SMBUS_QUICK,NULL);
+	                      value,0,I2C_SMBUS_QUICK,NULL);
 }
 
 s32 i2c_smbus_read_byte(struct i2c_client *client)
@@ -996,11 +993,11 @@
 			      I2C_SMBUS_I2C_BLOCK_DATA, &data);
 }
 
-/* Simulate a SMBus command using the i2c protocol 
+/* Simulate a SMBus command using the i2c protocol
    No checking of parameters is done!  */
-static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, 
+static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                    unsigned short flags,
-                                   char read_write, u8 command, int size, 
+                                   char read_write, u8 command, int size,
                                    union i2c_smbus_data * data)
 {
 	/* So we need to generate a series of msgs. In the case of writing, we
@@ -1010,7 +1007,7 @@
 	unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
 	unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
 	int num = read_write == I2C_SMBUS_READ?2:1;
-	struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, 
+	struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
 	                          { addr, flags | I2C_M_RD, 0, msgbuf1 }
 	                        };
 	int i;
@@ -1103,14 +1100,14 @@
 	if (i) {
 		/* Compute PEC if first message is a write */
 		if (!(msg[0].flags & I2C_M_RD)) {
-		 	if (num == 1) /* Write only */
+			if (num == 1) /* Write only */
 				i2c_smbus_add_pec(&msg[0]);
 			else /* Write followed by read */
 				partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
 		}
 		/* Ask for PEC if last message is a read */
 		if (msg[num-1].flags & I2C_M_RD)
-		 	msg[num-1].len++;
+			msg[num-1].len++;
 	}
 
 	if (i2c_transfer(adapter, msg, num) < 0)
@@ -1130,7 +1127,7 @@
 			case I2C_SMBUS_BYTE_DATA:
 				data->byte = msgbuf1[0];
 				break;
-			case I2C_SMBUS_WORD_DATA: 
+			case I2C_SMBUS_WORD_DATA:
 			case I2C_SMBUS_PROC_CALL:
 				data->word = msgbuf1[0] | (msgbuf1[1] << 8);
 				break;
@@ -1146,7 +1143,7 @@
 
 
 s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
-                   char read_write, u8 command, int size, 
+                   char read_write, u8 command, int size,
                    union i2c_smbus_data * data)
 {
 	s32 res;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 2e22a2f..ac5bd2a 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -1,5 +1,5 @@
 /*
-    i2c-dev.c - i2c-bus driver, char device interface  
+    i2c-dev.c - i2c-bus driver, char device interface
 
     Copyright (C) 1995-97 Simon G. Vogl
     Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
@@ -90,6 +90,7 @@
 	spin_lock(&i2c_dev_list_lock);
 	list_del(&i2c_dev->list);
 	spin_unlock(&i2c_dev_list_lock);
+	kfree(i2c_dev);
 }
 
 static ssize_t show_adapter_name(struct device *dev,
@@ -172,7 +173,7 @@
 	switch ( cmd ) {
 	case I2C_SLAVE:
 	case I2C_SLAVE_FORCE:
-		if ((arg > 0x3ff) || 
+		if ((arg > 0x3ff) ||
 		    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
 			return -EINVAL;
 		if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
@@ -193,12 +194,11 @@
 		return 0;
 	case I2C_FUNCS:
 		funcs = i2c_get_functionality(client->adapter);
-		return (copy_to_user((unsigned long __user *)arg, &funcs,
-		                     sizeof(unsigned long)))?-EFAULT:0;
+		return put_user(funcs, (unsigned long __user *)arg);
 
 	case I2C_RDWR:
-		if (copy_from_user(&rdwr_arg, 
-				   (struct i2c_rdwr_ioctl_data __user *)arg, 
+		if (copy_from_user(&rdwr_arg,
+				   (struct i2c_rdwr_ioctl_data __user *)arg,
 				   sizeof(rdwr_arg)))
 			return -EFAULT;
 
@@ -206,9 +206,9 @@
 		 * be sent at once */
 		if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
 			return -EINVAL;
-		
+
 		rdwr_pa = (struct i2c_msg *)
-			kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), 
+			kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
 			GFP_KERNEL);
 
 		if (rdwr_pa == NULL) return -ENOMEM;
@@ -278,9 +278,9 @@
 		                   (struct i2c_smbus_ioctl_data __user *) arg,
 		                   sizeof(struct i2c_smbus_ioctl_data)))
 			return -EFAULT;
-		if ((data_arg.size != I2C_SMBUS_BYTE) && 
+		if ((data_arg.size != I2C_SMBUS_BYTE) &&
 		    (data_arg.size != I2C_SMBUS_QUICK) &&
-		    (data_arg.size != I2C_SMBUS_BYTE_DATA) && 
+		    (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
 		    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
 		    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
 		    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
@@ -291,11 +291,11 @@
 				data_arg.size);
 			return -EINVAL;
 		}
-		/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, 
+		/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
 		   so the check is valid if size==I2C_SMBUS_QUICK too. */
-		if ((data_arg.read_write != I2C_SMBUS_READ) && 
+		if ((data_arg.read_write != I2C_SMBUS_READ) &&
 		    (data_arg.read_write != I2C_SMBUS_WRITE)) {
-			dev_dbg(&client->adapter->dev, 
+			dev_dbg(&client->adapter->dev,
 				"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
 				data_arg.read_write);
 			return -EINVAL;
@@ -304,7 +304,7 @@
 		/* Note that command values are always valid! */
 
 		if ((data_arg.size == I2C_SMBUS_QUICK) ||
-		    ((data_arg.size == I2C_SMBUS_BYTE) && 
+		    ((data_arg.size == I2C_SMBUS_BYTE) &&
 		    (data_arg.read_write == I2C_SMBUS_WRITE)))
 			/* These are special: we do not use data */
 			return i2c_smbus_xfer(client->adapter, client->addr,
@@ -322,14 +322,14 @@
 		if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
 		    (data_arg.size == I2C_SMBUS_BYTE))
 			datasize = sizeof(data_arg.data->byte);
-		else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || 
+		else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
 		         (data_arg.size == I2C_SMBUS_PROC_CALL))
 			datasize = sizeof(data_arg.data->word);
 		else /* size == smbus block, i2c block, or block proc. call */
 			datasize = sizeof(data_arg.data->block);
 
-		if ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
-		    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || 
+		if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+		    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
 		    (data_arg.read_write == I2C_SMBUS_WRITE)) {
 			if (copy_from_user(&temp, data_arg.data, datasize))
 				return -EFAULT;
@@ -337,8 +337,8 @@
 		res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 		      data_arg.read_write,
 		      data_arg.command,data_arg.size,&temp);
-		if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
-		              (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || 
+		if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+		              (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
 			      (data_arg.read_write == I2C_SMBUS_READ))) {
 			if (copy_to_user(data_arg.data, &temp, datasize))
 				return -EFAULT;
@@ -417,8 +417,8 @@
 	i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
 				     MKDEV(I2C_MAJOR, adap->nr),
 				     "i2c-%d", adap->nr);
-	if (!i2c_dev->dev) {
-		res = -ENODEV;
+	if (IS_ERR(i2c_dev->dev)) {
+		res = PTR_ERR(i2c_dev->dev);
 		goto error;
 	}
 	res = device_create_file(i2c_dev->dev, &dev_attr_name);
@@ -432,7 +432,6 @@
 	device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
 error:
 	return_i2c_dev(i2c_dev);
-	kfree(i2c_dev);
 	return res;
 }
 
@@ -447,7 +446,6 @@
 	device_remove_file(i2c_dev->dev, &dev_attr_name);
 	return_i2c_dev(i2c_dev);
 	device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
-	kfree(i2c_dev);
 
 	pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
 	return 0;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index dad9c47..5a5c565 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1000,10 +1000,6 @@
 	/* needs drive->queue to be set */
 	ide_toggle_bounce(drive, 1);
 
-	/* enable led activity for disk drives only */
-	if (drive->media == ide_disk && hwif->led_act)
-		blk_queue_activity_fn(q, hwif->led_act, drive);
-
 	return 0;
 }
 
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 13a6179..fbb7f14 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1485,7 +1485,7 @@
 
                         }
 
-                        i2c_bit_del_bus(i2c_ad);
+			i2c_del_adapter(i2c_ad);
 			kfree(i2c_ad);
                 }
         }
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3d5f196..6b46c9b 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -146,7 +146,7 @@
 
 config TOUCHSCREEN_UCB1400
 	tristate "Philips UCB1400 touchscreen"
-	depends on SND_AC97_BUS
+	select AC97_BUS
 	help
 	  This enables support for the Philips UCB1400 touchscreen interface.
 	  The UCB1400 is an AC97 audio codec.  The touchscreen interface
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 8e4ce10..ffda71d 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -650,7 +650,7 @@
 	/* dvb */
 	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
 	if (ret < 0)
-		goto err_i2c_bit_del_bus;
+		goto err_i2c_del_adapter;
 
 	dvb_adapter = &pluto->dvb_adapter;
 
@@ -712,8 +712,8 @@
 	dvb_dmx_release(dvbdemux);
 err_dvb_unregister_adapter:
 	dvb_unregister_adapter(dvb_adapter);
-err_i2c_bit_del_bus:
-	i2c_bit_del_bus(&pluto->i2c_adap);
+err_i2c_del_adapter:
+	i2c_del_adapter(&pluto->i2c_adap);
 err_pluto_hw_exit:
 	pluto_hw_exit(pluto);
 err_free_irq:
@@ -748,7 +748,7 @@
 	dvb_dmxdev_release(&pluto->dmxdev);
 	dvb_dmx_release(dvbdemux);
 	dvb_unregister_adapter(dvb_adapter);
-	i2c_bit_del_bus(&pluto->i2c_adap);
+	i2c_del_adapter(&pluto->i2c_adap);
 	pluto_hw_exit(pluto);
 	free_irq(pdev->irq, pluto);
 	pci_iounmap(pdev, pluto->io_mem);
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index 70de6c9..62b8730 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -479,11 +479,7 @@
 	if (0 != btv->i2c_rc)
 		return 0;
 
-	if (btv->use_i2c_hw) {
-		return i2c_del_adapter(&btv->c.i2c_adap);
-	} else {
-		return i2c_bit_del_bus(&btv->c.i2c_adap);
-	}
+	return i2c_del_adapter(&btv->c.i2c_adap);
 }
 
 /*
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 4b655f2..453af5e 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1153,7 +1153,7 @@
 	mutex_lock(&devlist);
 	cx88_ir_fini(core);
 	if (0 == core->i2c_rc)
-		i2c_bit_del_bus(&core->i2c_adap);
+		i2c_del_adapter(&core->i2c_adap);
 	list_del(&core->devlist);
 	iounmap(core->lmmio);
 	cx88_devcount--;
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index 2b4f197..6068c9b 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -168,7 +168,7 @@
 	    dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
 		return;
 
-	i2c_bit_del_bus(&vp3054_i2c->adap);
+	i2c_del_adapter(&vp3054_i2c->adap);
 	kfree(vp3054_i2c);
 }
 
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 92bf9a1..0f3fba7 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -50,6 +50,11 @@
 #define PDEBUG(level, fmt, args...) \
 		if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
 
+static int usbvision_i2c_write(void *data, unsigned char addr, char *buf,
+			    short len);
+static int usbvision_i2c_read(void *data, unsigned char addr, char *buf,
+			   short len);
+
 static inline int try_write_address(struct i2c_adapter *i2c_adap,
 				    unsigned char addr, int retries)
 {
@@ -61,7 +66,7 @@
 	data = i2c_get_adapdata(i2c_adap);
 	buf[0] = 0x00;
 	for (i = 0; i <= retries; i++) {
-		ret = (adap->outb(data, addr, buf, 1));
+		ret = (usbvision_i2c_write(data, addr, buf, 1));
 		if (ret == 1)
 			break;	/* success! */
 		udelay(5 /*adap->udelay */ );
@@ -86,7 +91,7 @@
 
 	data = i2c_get_adapdata(i2c_adap);
 	for (i = 0; i <= retries; i++) {
-		ret = (adap->inb(data, addr, buf, 1));
+		ret = (usbvision_i2c_read(data, addr, buf, 1));
 		if (ret == 1)
 			break;	/* success! */
 		udelay(5 /*adap->udelay */ );
@@ -153,7 +158,6 @@
 usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
 {
 	struct i2c_msg *pmsg;
-	struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
 	void *data;
 	int i, ret;
 	unsigned char addr;
@@ -170,13 +174,13 @@
 
 		if (pmsg->flags & I2C_M_RD) {
 			/* read bytes into buffer */
-			ret = (adap->inb(data, addr, pmsg->buf, pmsg->len));
+			ret = (usbvision_i2c_read(data, addr, pmsg->buf, pmsg->len));
 			if (ret < pmsg->len) {
 				return (ret < 0) ? ret : -EREMOTEIO;
 			}
 		} else {
 			/* write bytes from buffer */
-			ret = (adap->outb(data, addr, pmsg->buf, pmsg->len));
+			ret = (usbvision_i2c_write(data, addr, pmsg->buf, pmsg->len));
 			if (ret < pmsg->len) {
 				return (ret < 0) ? ret : -EREMOTEIO;
 			}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 6b6dff4..a373c14 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -782,7 +782,7 @@
 
 static int vino_i2c_del_bus(void)
 {
-	return i2c_sgi_del_bus(&vino_i2c_adapter);
+	return i2c_del_adapter(&vino_i2c_adapter);
 }
 
 static int i2c_camera_command(unsigned int cmd, void *arg)
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 653822c..4d1eb2f 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -849,7 +849,7 @@
 static void
 zoran_unregister_i2c (struct zoran *zr)
 {
-	i2c_bit_del_bus((&zr->i2c_adapter));
+	i2c_del_adapter(&zr->i2c_adapter);
 }
 
 /* Check a zoran_params struct for correctness, insert default params */
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 4633dbc..08a33c3 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ *  linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver
  *
  *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
  *
@@ -11,7 +11,7 @@
  */
 
 /*
-   This is the AT91RM9200 MCI driver that has been tested with both MMC cards
+   This is the AT91 MCI driver that has been tested with both MMC cards
    and SD-cards.  Boards that support write protect are now supported.
    The CCAT91SBC001 board does not support SD cards.
 
@@ -38,8 +38,8 @@
      controller to manage the transfers.
 
      A read is done from the controller directly to the scatterlist passed in from the request.
-     Due to a bug in the controller, when a read is completed, all the words are byte
-     swapped in the scatterlist buffers.
+     Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
+     swapped in the scatterlist buffers.  AT91SAM926x are not affected by this bug.
 
      The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
 
@@ -72,6 +72,7 @@
 #include <asm/irq.h>
 #include <asm/mach/mmc.h>
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/at91_mci.h>
 #include <asm/arch/at91_pdc.h>
@@ -80,34 +81,18 @@
 
 #undef	SUPPORT_4WIRE
 
-static struct clk *mci_clk;
+#define FL_SENT_COMMAND	(1 << 0)
+#define FL_SENT_STOP	(1 << 1)
 
-#define FL_SENT_COMMAND (1 << 0)
-#define FL_SENT_STOP (1 << 1)
+#define AT91_MCI_ERRORS	(AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE	\
+		| AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE		\
+		| AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)			
 
+#define at91_mci_read(host, reg)	__raw_readl((host)->baseaddr + (reg))
+#define at91_mci_write(host, reg, val)	__raw_writel((val), (host)->baseaddr + (reg))
 
 
 /*
- * Read from a MCI register.
- */
-static inline unsigned long at91_mci_read(unsigned int reg)
-{
-	void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
-
-	return __raw_readl(mci_base + reg);
-}
-
-/*
- * Write to a MCI register.
- */
-static inline void at91_mci_write(unsigned int reg, unsigned long value)
-{
-        void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
-
-        __raw_writel(value, mci_base + reg);
-}
-
-/*
  * Low level type for this driver
  */
 struct at91mci_host
@@ -116,9 +101,14 @@
 	struct mmc_command *cmd;
 	struct mmc_request *request;
 
+	void __iomem *baseaddr;
+	int irq;
+
 	struct at91_mmc_data *board;
 	int present;
 
+	struct clk *mci_clk;
+
 	/*
 	 * Flag indicating when the command has been sent. This is used to
 	 * work out whether or not to send the stop
@@ -158,7 +148,6 @@
 	for (i = 0; i < len; i++) {
 		struct scatterlist *sg;
 		int amount;
-		int index;
 		unsigned int *sgbuffer;
 
 		sg = &data->sg[i];
@@ -166,10 +155,15 @@
 		sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
 		amount = min(size, sg->length);
 		size -= amount;
-		amount /= 4;
 
-		for (index = 0; index < amount; index++)
-			*dmabuf++ = swab32(sgbuffer[index]);
+		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
+			int index;
+
+			for (index = 0; index < (amount / 4); index++)
+				*dmabuf++ = swab32(sgbuffer[index]);
+		}
+		else
+			memcpy(dmabuf, sgbuffer, amount);
 
 		kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
 
@@ -217,13 +211,13 @@
 
 		/* Check to see if this needs filling */
 		if (i == 0) {
-			if (at91_mci_read(AT91_PDC_RCR) != 0) {
+			if (at91_mci_read(host, AT91_PDC_RCR) != 0) {
 				pr_debug("Transfer active in current\n");
 				continue;
 			}
 		}
 		else {
-			if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+			if (at91_mci_read(host, AT91_PDC_RNCR) != 0) {
 				pr_debug("Transfer active in next\n");
 				continue;
 			}
@@ -240,12 +234,12 @@
 		pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
 
 		if (i == 0) {
-			at91_mci_write(AT91_PDC_RPR, sg->dma_address);
-			at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+			at91_mci_write(host, AT91_PDC_RPR, sg->dma_address);
+			at91_mci_write(host, AT91_PDC_RCR, sg->length / 4);
 		}
 		else {
-			at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
-			at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+			at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address);
+			at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4);
 		}
 	}
 
@@ -276,8 +270,6 @@
 
 	while (host->in_use_index < host->transfer_index) {
 		unsigned int *buffer;
-		int index;
-		int len;
 
 		struct scatterlist *sg;
 
@@ -295,11 +287,13 @@
 
 		data->bytes_xfered += sg->length;
 
-		len = sg->length / 4;
+		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
+			int index;
 
-		for (index = 0; index < len; index++) {
-			buffer[index] = swab32(buffer[index]);
+			for (index = 0; index < (sg->length / 4); index++)
+				buffer[index] = swab32(buffer[index]);
 		}
+
 		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
 		flush_dcache_page(sg->page);
 	}
@@ -308,8 +302,8 @@
 	if (host->transfer_index < data->sg_len)
 		at91mci_pre_dma_read(host);
 	else {
-		at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
-		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+		at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
 	}
 
 	pr_debug("post dma read done\n");
@@ -326,11 +320,11 @@
 	pr_debug("Handling the transmit\n");
 
 	/* Disable the transfer */
-	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+	at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
 
 	/* Now wait for cmd ready */
-	at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
-	at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
+	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
 
 	cmd = host->cmd;
 	if (!cmd) return;
@@ -344,21 +338,23 @@
 /*
  * Enable the controller
  */
-static void at91_mci_enable(void)
+static void at91_mci_enable(struct at91mci_host *host)
 {
-	at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
-	at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
-	at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-	at91_mci_write(AT91_MCI_MR, 0x834A);
-	at91_mci_write(AT91_MCI_SDCR, 0x0);
+	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
+	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+	at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+	at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+
+	/* use Slot A or B (only one at same time) */
+	at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
 }
 
 /*
  * Disable the controller
  */
-static void at91_mci_disable(void)
+static void at91_mci_disable(struct at91mci_host *host)
 {
-	at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
 }
 
 /*
@@ -378,13 +374,13 @@
 
 	/* Not sure if this is needed */
 #if 0
-	if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+	if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
 		pr_debug("Clearing timeout\n");
-		at91_mci_write(AT91_MCI_ARGR, 0);
-		at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
-		while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+		at91_mci_write(host, AT91_MCI_ARGR, 0);
+		at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+		while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
 			/* spin */
-			pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+			pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
 		}
 	}
 #endif
@@ -431,32 +427,32 @@
 	/*
 	 * Set the arguments and send the command
 	 */
-	pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
-		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+	pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
+		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
 
 	if (!data) {
-		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
-		at91_mci_write(AT91_PDC_RPR, 0);
-		at91_mci_write(AT91_PDC_RCR, 0);
-		at91_mci_write(AT91_PDC_RNPR, 0);
-		at91_mci_write(AT91_PDC_RNCR, 0);
-		at91_mci_write(AT91_PDC_TPR, 0);
-		at91_mci_write(AT91_PDC_TCR, 0);
-		at91_mci_write(AT91_PDC_TNPR, 0);
-		at91_mci_write(AT91_PDC_TNCR, 0);
+		at91_mci_write(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(AT91_MCI_ARGR, cmd->arg);
-		at91_mci_write(AT91_MCI_CMDR, cmdr);
+		at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+		at91_mci_write(host, AT91_MCI_CMDR, cmdr);
 		return AT91_MCI_CMDRDY;
 	}
 
-	mr = at91_mci_read(AT91_MCI_MR) & 0x7fff;	/* zero block length and PDC mode */
-	at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+	mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;	/* zero block length and PDC mode */
+	at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
 
 	/*
 	 * Disable the PDC controller
 	 */
-	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+	at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
 
 	if (cmdr & AT91_MCI_TRCMD_START) {
 		data->bytes_xfered = 0;
@@ -485,8 +481,8 @@
 
 			pr_debug("Transmitting %d bytes\n", host->total_length);
 
-			at91_mci_write(AT91_PDC_TPR, host->physical_address);
-			at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+			at91_mci_write(host, AT91_PDC_TPR, host->physical_address);
+			at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4);
 			ier = AT91_MCI_TXBUFE;
 		}
 	}
@@ -496,14 +492,14 @@
 	 * the data sheet says
 	 */
 
-	at91_mci_write(AT91_MCI_ARGR, cmd->arg);
-	at91_mci_write(AT91_MCI_CMDR, cmdr);
+	at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+	at91_mci_write(host, AT91_MCI_CMDR, cmdr);
 
 	if (cmdr & AT91_MCI_TRCMD_START) {
 		if (cmdr & AT91_MCI_TRDIR)
-			at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+			at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN);
 		else
-			at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN);
+			at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN);
 	}
 	return ier;
 }
@@ -520,7 +516,7 @@
 	pr_debug("setting ier to %08X\n", ier);
 
 	/* Stop on errors or the required value */
-	at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
 }
 
 /*
@@ -548,19 +544,19 @@
 	struct mmc_command *cmd = host->cmd;
 	unsigned int status;
 
-	at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
 
-	cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
-	cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
-	cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
-	cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+	cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
+	cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
+	cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
+	cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
 
 	if (host->buffer) {
 		dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
 		host->buffer = NULL;
 	}
 
-	status = at91_mci_read(AT91_MCI_SR);
+	status = at91_mci_read(host, AT91_MCI_SR);
 
 	pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
 		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
@@ -611,18 +607,18 @@
 {
 	int clkdiv;
 	struct at91mci_host *host = mmc_priv(mmc);
-	unsigned long at91_master_clock = clk_get_rate(mci_clk);
+	unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
 
 	host->bus_mode = ios->bus_mode;
 
 	if (ios->clock == 0) {
 		/* Disable the MCI controller */
-		at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+		at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
 		clkdiv = 0;
 	}
 	else {
 		/* Enable the MCI controller */
-		at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+		at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
 
 		if ((at91_master_clock % (ios->clock * 2)) == 0)
 			clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
@@ -634,25 +630,25 @@
 	}
 	if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
 		pr_debug("MMC: Setting controller bus width to 4\n");
-		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+		at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
 	}
 	else {
 		pr_debug("MMC: Setting controller bus width to 1\n");
-		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+		at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
 	}
 
 	/* Set the clock divider */
-	at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+	at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
 
 	/* maybe switch power to the card */
 	if (host->board->vcc_pin) {
 		switch (ios->power_mode) {
 			case MMC_POWER_OFF:
-				at91_set_gpio_output(host->board->vcc_pin, 0);
+				at91_set_gpio_value(host->board->vcc_pin, 0);
 				break;
 			case MMC_POWER_UP:
 			case MMC_POWER_ON:
-				at91_set_gpio_output(host->board->vcc_pin, 1);
+				at91_set_gpio_value(host->board->vcc_pin, 1);
 				break;
 		}
 	}
@@ -665,39 +661,40 @@
 {
 	struct at91mci_host *host = devid;
 	int completed = 0;
+	unsigned int int_status, int_mask;
 
-	unsigned int int_status;
+	int_status = at91_mci_read(host, AT91_MCI_SR);
+	int_mask = at91_mci_read(host, AT91_MCI_IMR);
+	
+	pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
+		int_status & int_mask);
+	
+	int_status = int_status & int_mask;
 
-	int_status = at91_mci_read(AT91_MCI_SR);
-	pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
-		int_status & at91_mci_read(AT91_MCI_IMR));
-
-	if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+	if (int_status & AT91_MCI_ERRORS) {
 		completed = 1;
+		
+		if (int_status & AT91_MCI_UNRE)
+			pr_debug("MMC: Underrun error\n");
+		if (int_status & AT91_MCI_OVRE)
+			pr_debug("MMC: Overrun error\n");
+		if (int_status & AT91_MCI_DTOE)
+			pr_debug("MMC: Data timeout\n");
+		if (int_status & AT91_MCI_DCRCE)
+			pr_debug("MMC: CRC error in data\n");
+		if (int_status & AT91_MCI_RTOE)
+			pr_debug("MMC: Response timeout\n");
+		if (int_status & AT91_MCI_RENDE)
+			pr_debug("MMC: Response end bit error\n");
+		if (int_status & AT91_MCI_RCRCE)
+			pr_debug("MMC: Response CRC error\n");
+		if (int_status & AT91_MCI_RDIRE)
+			pr_debug("MMC: Response direction error\n");
+		if (int_status & AT91_MCI_RINDE)
+			pr_debug("MMC: Response index error\n");
+	} else {
+		/* Only continue processing if no errors */
 
-	int_status &= at91_mci_read(AT91_MCI_IMR);
-
-	if (int_status & AT91_MCI_UNRE)
-		pr_debug("MMC: Underrun error\n");
-	if (int_status & AT91_MCI_OVRE)
-		pr_debug("MMC: Overrun error\n");
-	if (int_status & AT91_MCI_DTOE)
-		pr_debug("MMC: Data timeout\n");
-	if (int_status & AT91_MCI_DCRCE)
-		pr_debug("MMC: CRC error in data\n");
-	if (int_status & AT91_MCI_RTOE)
-		pr_debug("MMC: Response timeout\n");
-	if (int_status & AT91_MCI_RENDE)
-		pr_debug("MMC: Response end bit error\n");
-	if (int_status & AT91_MCI_RCRCE)
-		pr_debug("MMC: Response CRC error\n");
-	if (int_status & AT91_MCI_RDIRE)
-		pr_debug("MMC: Response direction error\n");
-	if (int_status & AT91_MCI_RINDE)
-		pr_debug("MMC: Response index error\n");
-
-	/* Only continue processing if no errors */
-	if (!completed) {
 		if (int_status & AT91_MCI_TXBUFE) {
 			pr_debug("TX buffer empty\n");
 			at91_mci_handle_transmitted(host);
@@ -705,12 +702,11 @@
 
 		if (int_status & AT91_MCI_RXBUFF) {
 			pr_debug("RX buffer full\n");
-			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
 		}
 
-		if (int_status & AT91_MCI_ENDTX) {
+		if (int_status & AT91_MCI_ENDTX)
 			pr_debug("Transmit has ended\n");
-		}
 
 		if (int_status & AT91_MCI_ENDRX) {
 			pr_debug("Receive has ended\n");
@@ -719,37 +715,33 @@
 
 		if (int_status & AT91_MCI_NOTBUSY) {
 			pr_debug("Card is ready\n");
-			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
 		}
 
-		if (int_status & AT91_MCI_DTIP) {
+		if (int_status & AT91_MCI_DTIP)
 			pr_debug("Data transfer in progress\n");
-		}
 
-		if (int_status & AT91_MCI_BLKE) {
+		if (int_status & AT91_MCI_BLKE)
 			pr_debug("Block transfer has ended\n");
-		}
 
-		if (int_status & AT91_MCI_TXRDY) {
+		if (int_status & AT91_MCI_TXRDY)
 			pr_debug("Ready to transmit\n");
-		}
 
-		if (int_status & AT91_MCI_RXRDY) {
+		if (int_status & AT91_MCI_RXRDY)
 			pr_debug("Ready to receive\n");
-		}
 
 		if (int_status & AT91_MCI_CMDRDY) {
 			pr_debug("Command ready\n");
 			completed = 1;
 		}
 	}
-	at91_mci_write(AT91_MCI_IDR, int_status);
 
 	if (completed) {
 		pr_debug("Completed command\n");
-		at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+		at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
 		at91mci_completed_command(host);
-	}
+	} else
+		at91_mci_write(host, AT91_MCI_IDR, int_status);
 
 	return IRQ_HANDLED;
 }
@@ -769,7 +761,7 @@
 			present ? "insert" : "remove");
 		if (!present) {
 			pr_debug("****** Resetting SD-card bus width ******\n");
-			at91_mci_write(AT91_MCI_SDCR, 0);
+			at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
 		}
 		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
 	}
@@ -806,15 +798,22 @@
 {
 	struct mmc_host *mmc;
 	struct at91mci_host *host;
+	struct resource *res;
 	int ret;
 
 	pr_debug("Probe MCI devices\n");
-	at91_mci_disable();
-	at91_mci_enable();
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
+		return -EBUSY;
 
 	mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
 	if (!mmc) {
 		pr_debug("Failed to allocate mmc host\n");
+		release_mem_region(res->start, res->end - res->start + 1);
 		return -ENOMEM;
 	}
 
@@ -833,30 +832,51 @@
 #ifdef SUPPORT_4WIRE
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 #else
-		printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+		printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
 #endif
 	}
 
 	/*
 	 * Get Clock
 	 */
-	mci_clk = clk_get(&pdev->dev, "mci_clk");
-	if (IS_ERR(mci_clk)) {
+	host->mci_clk = clk_get(&pdev->dev, "mci_clk");
+	if (IS_ERR(host->mci_clk)) {
 		printk(KERN_ERR "AT91 MMC: no clock defined.\n");
 		mmc_free_host(mmc);
+		release_mem_region(res->start, res->end - res->start + 1);
 		return -ENODEV;
 	}
-	clk_enable(mci_clk);			/* Enable the peripheral clock */
+
+	/*
+	 * Map I/O region
+	 */
+	host->baseaddr = ioremap(res->start, res->end - res->start + 1);
+	if (!host->baseaddr) {
+		clk_put(host->mci_clk);
+		mmc_free_host(mmc);
+		release_mem_region(res->start, res->end - res->start + 1);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Reset hardware
+	 */
+	clk_enable(host->mci_clk);		/* Enable the peripheral clock */
+	at91_mci_disable(host);
+	at91_mci_enable(host);
 
 	/*
 	 * Allocate the MCI interrupt
 	 */
-	ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+	host->irq = platform_get_irq(pdev, 0);
+	ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
 	if (ret) {
-		printk(KERN_ERR "Failed to request MCI interrupt\n");
-		clk_disable(mci_clk);
-		clk_put(mci_clk);
+		printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
+		clk_disable(host->mci_clk);
+		clk_put(host->mci_clk);
 		mmc_free_host(mmc);
+		iounmap(host->baseaddr);
+		release_mem_region(res->start, res->end - res->start + 1);
 		return ret;
 	}
 
@@ -879,10 +899,10 @@
 		ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
 				0, DRIVER_NAME, host);
 		if (ret)
-			printk(KERN_ERR "couldn't allocate MMC detect irq\n");
+			printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
 	}
 
-	pr_debug(KERN_INFO "Added MCI driver\n");
+	pr_debug("Added MCI driver\n");
 
 	return 0;
 }
@@ -894,6 +914,7 @@
 {
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
 	struct at91mci_host *host;
+	struct resource *res;
 
 	if (!mmc)
 		return -1;
@@ -905,16 +926,19 @@
 		cancel_delayed_work(&host->mmc->detect);
 	}
 
+	at91_mci_disable(host);
 	mmc_remove_host(mmc);
-	at91_mci_disable();
-	free_irq(AT91RM9200_ID_MCI, host);
+	free_irq(host->irq, host);
+
+	clk_disable(host->mci_clk);			/* Disable the peripheral clock */
+	clk_put(host->mci_clk);
+
+	iounmap(host->baseaddr);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+
 	mmc_free_host(mmc);
-
-	clk_disable(mci_clk);				/* Disable the peripheral clock */
-	clk_put(mci_clk);
-
 	platform_set_drvdata(pdev, NULL);
-
 	pr_debug("MCI Removed\n");
 
 	return 0;
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index a17423a..3e35a43 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -78,8 +78,10 @@
 		spin_unlock_irq(q->queue_lock);
 
 		if (!req) {
-			if (kthread_should_stop())
+			if (kthread_should_stop()) {
+				set_current_state(TASK_RUNNING);
 				break;
+			}
 			up(&mq->thread_sem);
 			schedule();
 			down(&mq->thread_sem);
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index cd98117..c2d13d7 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -1170,8 +1170,8 @@
 	}
 
 	if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
-		printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n");
-		return -ENODEV;
+		printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. "
+			"You may experience problems.\n");
 	}
 
 	if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 931028f..35ad5cf 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -2131,14 +2131,15 @@
 	}
 
 	if (done) {
+		unsigned long flags;
 		/*
 		 * Order is important since data can get interrupted
 		 * again when we think we are done.
 		 */
-		local_irq_disable();
+		local_irq_save(flags);
 		RTL_W16_F(IntrMask, rtl8139_intr_mask);
 		__netif_rx_complete(dev);
-		local_irq_enable();
+		local_irq_restore(flags);
 	}
 	spin_unlock(&tp->rx_lock);
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9de0eed..8aa8dd0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2384,6 +2384,14 @@
           Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
           are using only 10G cards say 'N' here.
 
+config CHELSIO_T1_NAPI
+	bool "Use Rx Polling (NAPI)"
+	depends on CHELSIO_T1
+	default y
+	help
+	  NAPI is a driver API designed to reduce CPU and interrupt load
+	  when the driver is receiving lots of packets from the card.
+
 config EHEA
 	tristate "eHEA Ethernet support"
 	depends on IBMEBUS
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index de48ead..fd5d821f 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -220,9 +220,8 @@
 
 	t1_interrupts_clear(adapter);
 
-	adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0;
-	err = request_irq(adapter->pdev->irq,
-			  t1_select_intr_handler(adapter),
+	adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
+	err = request_irq(adapter->pdev->irq, t1_interrupt,
 			  adapter->params.has_msi ? 0 : IRQF_SHARED,
 			  adapter->name, adapter);
 	if (err) {
@@ -764,18 +763,7 @@
 {
 	struct adapter *adapter = dev->priv;
 
-	/*
-	 * If RX coalescing is requested we use NAPI, otherwise interrupts.
-	 * This choice can be made only when all ports and the TOE are off.
-	 */
-	if (adapter->open_device_map == 0)
-		adapter->params.sge.polling = c->use_adaptive_rx_coalesce;
-
-	if (adapter->params.sge.polling) {
-		adapter->params.sge.rx_coalesce_usecs = 0;
-	} else {
-		adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
-	}
+	adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
  	adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
 	adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
 	t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
@@ -944,7 +932,7 @@
 	struct adapter *adapter = dev->priv;
 
 	local_irq_save(flags);
-	t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
+	t1_interrupt(adapter->pdev->irq, adapter);
 	local_irq_restore(flags);
 }
 #endif
@@ -1165,7 +1153,10 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 		netdev->poll_controller = t1_netpoll;
 #endif
+#ifdef CONFIG_CHELSIO_T1_NAPI
 		netdev->weight = 64;
+		netdev->poll = t1_poll;
+#endif
 
 		SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
 	}
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 0ca8d87..659cb22 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1413,16 +1413,20 @@
 
 	if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
 		st->vlan_xtract++;
-		if (adapter->params.sge.polling)
+#ifdef CONFIG_CHELSIO_T1_NAPI
 			vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
 						 ntohs(p->vlan));
-		else
+#else
 			vlan_hwaccel_rx(skb, adapter->vlan_grp,
 					ntohs(p->vlan));
-	} else if (adapter->params.sge.polling)
+#endif
+	} else {
+#ifdef CONFIG_CHELSIO_T1_NAPI
 		netif_receive_skb(skb);
-	else
+#else
 		netif_rx(skb);
+#endif
+	}
 	return 0;
 }
 
@@ -1572,6 +1576,7 @@
 	return budget;
 }
 
+#ifdef CONFIG_CHELSIO_T1_NAPI
 /*
  * A simpler version of process_responses() that handles only pure (i.e.,
  * non data-carrying) responses.  Such respones are too light-weight to justify
@@ -1619,92 +1624,76 @@
  * or protection from interrupts as data interrupts are off at this point and
  * other adapter interrupts do not interfere.
  */
-static int t1_poll(struct net_device *dev, int *budget)
+int t1_poll(struct net_device *dev, int *budget)
 {
 	struct adapter *adapter = dev->priv;
 	int effective_budget = min(*budget, dev->quota);
-
 	int work_done = process_responses(adapter, effective_budget);
+
 	*budget -= work_done;
 	dev->quota -= work_done;
 
 	if (work_done >= effective_budget)
 		return 1;
 
+ 	spin_lock_irq(&adapter->async_lock);
 	__netif_rx_complete(dev);
-
-	/*
-	 * Because we don't atomically flush the following write it is
-	 * possible that in very rare cases it can reach the device in a way
-	 * that races with a new response being written plus an error interrupt
-	 * causing the NAPI interrupt handler below to return unhandled status
-	 * to the OS.  To protect against this would require flushing the write
-	 * and doing both the write and the flush with interrupts off.  Way too
-	 * expensive and unjustifiable given the rarity of the race.
-	 */
 	writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
-	return 0;
-}
+	writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+	       adapter->regs + A_PL_ENABLE);
+ 	spin_unlock_irq(&adapter->async_lock);
 
-/*
- * Returns true if the device is already scheduled for polling.
- */
-static inline int napi_is_scheduled(struct net_device *dev)
-{
-	return test_bit(__LINK_STATE_RX_SCHED, &dev->state);
+	return 0;
 }
 
 /*
  * NAPI version of the main interrupt handler.
  */
-static irqreturn_t t1_interrupt_napi(int irq, void *data)
+irqreturn_t t1_interrupt(int irq, void *data)
 {
-	int handled;
 	struct adapter *adapter = data;
+ 	struct net_device *dev = adapter->sge->netdev;
 	struct sge *sge = adapter->sge;
-	struct respQ *q = &adapter->sge->respQ;
+ 	u32 cause;
+	int handled = 0;
 
-	/*
-	 * Clear the SGE_DATA interrupt first thing.  Normally the NAPI
-	 * handler has control of the response queue and the interrupt handler
-	 * can look at the queue reliably only once it knows NAPI is off.
-	 * We can't wait that long to clear the SGE_DATA interrupt because we
-	 * could race with t1_poll rearming the SGE interrupt, so we need to
-	 * clear the interrupt speculatively and really early on.
-	 */
-	writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+	cause = readl(adapter->regs + A_PL_CAUSE);
+	if (cause == 0 || cause == ~0)
+		return IRQ_NONE;
 
 	spin_lock(&adapter->async_lock);
-	if (!napi_is_scheduled(sge->netdev)) {
+ 	if (cause & F_PL_INTR_SGE_DATA) {
+		struct respQ *q = &adapter->sge->respQ;
 		struct respQ_e *e = &q->entries[q->cidx];
 
-		if (e->GenerationBit == q->genbit) {
-			if (e->DataValid ||
-			    process_pure_responses(adapter, e)) {
-				if (likely(__netif_rx_schedule_prep(sge->netdev)))
-					__netif_rx_schedule(sge->netdev);
-				else if (net_ratelimit())
-					printk(KERN_INFO
-					       "NAPI schedule failure!\n");
-			} else
-				writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ 		handled = 1;
+ 		writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
 
-			handled = 1;
-			goto unlock;
-		} else
-			writel(q->cidx, adapter->regs + A_SG_SLEEPING);
-	}  else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) {
-	        printk(KERN_ERR "data interrupt while NAPI running\n");
-	}
-	
-	handled = t1_slow_intr_handler(adapter);
+		if (e->GenerationBit == q->genbit &&
+		    __netif_rx_schedule_prep(dev)) {
+			if (e->DataValid || process_pure_responses(adapter, e)) {
+				/* mask off data IRQ */
+				writel(adapter->slow_intr_mask,
+				       adapter->regs + A_PL_ENABLE);
+				__netif_rx_schedule(sge->netdev);
+				goto unlock;
+			}
+			/* no data, no NAPI needed */
+			netif_poll_enable(dev);
+
+		}
+		writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+	} else
+		handled = t1_slow_intr_handler(adapter);
+
 	if (!handled)
 		sge->stats.unhandled_irqs++;
- unlock:
+unlock:
 	spin_unlock(&adapter->async_lock);
 	return IRQ_RETVAL(handled != 0);
 }
 
+#else
 /*
  * Main interrupt handler, optimized assuming that we took a 'DATA'
  * interrupt.
@@ -1720,7 +1709,7 @@
  * 5. If we took an interrupt, but no valid respQ descriptors was found we
  *      let the slow_intr_handler run and do error handling.
  */
-static irqreturn_t t1_interrupt(int irq, void *cookie)
+irqreturn_t t1_interrupt(int irq, void *cookie)
 {
 	int work_done;
 	struct respQ_e *e;
@@ -1752,11 +1741,7 @@
 	spin_unlock(&adapter->async_lock);
 	return IRQ_RETVAL(work_done != 0);
 }
-
-irq_handler_t t1_select_intr_handler(adapter_t *adapter)
-{
-	return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt;
-}
+#endif
 
 /*
  * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
@@ -2033,7 +2018,6 @@
  */
 int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p)
 {
-	sge->netdev->poll = t1_poll;
 	sge->fixed_intrtimer = p->rx_coalesce_usecs *
 		core_ticks_per_usec(sge->adapter);
 	writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER);
@@ -2234,7 +2218,6 @@
 
 	p->coalesce_enable = 0;
 	p->sample_interval_usecs = 0;
-	p->polling = 0;
 
 	return sge;
 nomem_port:
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 7ceb011..d132a0ef 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -76,7 +76,9 @@
 int t1_sge_configure(struct sge *, struct sge_params *);
 int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
 void t1_sge_destroy(struct sge *);
-irq_handler_t t1_select_intr_handler(adapter_t *adapter);
+irqreturn_t t1_interrupt(int irq, void *cookie);
+int t1_poll(struct net_device *, int *);
+
 int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
 void t1_set_vlan_accel(struct adapter *adapter, int on_off);
 void t1_sge_start(struct sge *);
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 8a83db0..153b6dc 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -1177,7 +1177,7 @@
 	dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */
 	dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
 	memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
-	memcpy(dev->dev_addr, &ax25_nocall, AX25_ADDR_LEN);
+	memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN);
 	dev->tx_queue_len = 16;
 
 	/* New style flags */
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index bd0ce98..25b559b 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -264,12 +264,12 @@
 	WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
 
 	for(; p < end; p++, reg++)
-		*p += readl(reg);
+		*p += __raw_readl(reg);
 }
 
-static void macb_periodic_task(void *arg)
+static void macb_periodic_task(struct work_struct *work)
 {
-	struct macb *bp = arg;
+	struct macb *bp = container_of(work, struct macb, periodic_task.work);
 
 	macb_update_stats(bp);
 	macb_check_media(bp, 1, 0);
@@ -1088,7 +1088,7 @@
 
 	dev->base_addr = regs->start;
 
-	INIT_WORK(&bp->periodic_task, macb_periodic_task, bp);
+	INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
 	mutex_init(&bp->mdio_mutex);
 	init_completion(&bp->mdio_complete);
 
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index 8c253db..27bf0ae 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -250,9 +250,9 @@
 
 /* Register access macros */
 #define macb_readl(port,reg)				\
-	readl((port)->regs + MACB_##reg)
+	__raw_readl((port)->regs + MACB_##reg)
 #define macb_writel(port,reg,value)			\
-	writel((value), (port)->regs + MACB_##reg)
+	__raw_writel((value), (port)->regs + MACB_##reg)
 
 struct dma_desc {
 	u32	addr;
@@ -377,7 +377,7 @@
 
 	unsigned int		rx_pending, tx_pending;
 
-	struct work_struct	periodic_task;
+	struct delayed_work	periodic_task;
 
 	struct mutex		mdio_mutex;
 	struct completion	mdio_complete;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 81f127a..94ac168 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -71,7 +71,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.0.0"
+#define MYRI10GE_VERSION_STR "1.1.0"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -92,8 +92,13 @@
 #define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
 #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
 
+#define MYRI10GE_ALLOC_ORDER 0
+#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
+#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
+
 struct myri10ge_rx_buffer_state {
-	struct sk_buff *skb;
+	struct page *page;
+	int page_offset;
 	 DECLARE_PCI_UNMAP_ADDR(bus)
 	 DECLARE_PCI_UNMAP_LEN(len)
 };
@@ -116,9 +121,14 @@
 	u8 __iomem *wc_fifo;	/* w/c rx dma addr fifo address */
 	struct mcp_kreq_ether_recv *shadow;	/* host shadow of recv ring */
 	struct myri10ge_rx_buffer_state *info;
+	struct page *page;
+	dma_addr_t bus;
+	int page_offset;
 	int cnt;
+	int fill_cnt;
 	int alloc_fail;
 	int mask;		/* number of rx slots -1 */
+	int watchdog_needed;
 };
 
 struct myri10ge_tx_buf {
@@ -150,6 +160,7 @@
 	struct myri10ge_rx_buf rx_big;
 	struct myri10ge_rx_done rx_done;
 	int small_bytes;
+	int big_bytes;
 	struct net_device *dev;
 	struct net_device_stats stats;
 	u8 __iomem *sram;
@@ -238,11 +249,6 @@
 MODULE_PARM_DESC(myri10ge_force_firmware,
 		 "Force firmware to assume aligned completions\n");
 
-static int myri10ge_skb_cross_4k = 0;
-module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(myri10ge_skb_cross_4k,
-		 "Can a small skb cross a 4KB boundary?\n");
-
 static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
 module_param(myri10ge_initial_mtu, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");
@@ -266,6 +272,10 @@
 module_param(myri10ge_debug, int, 0);
 MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
 
+static int myri10ge_fill_thresh = 256;
+module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
+
 #define MYRI10GE_FW_OFFSET 1024*1024
 #define MYRI10GE_HIGHPART_TO_U32(X) \
 (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -273,9 +283,9 @@
 
 #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
 
-static inline void put_be32(__be32 val, __be32 __iomem *p)
+static inline void put_be32(__be32 val, __be32 __iomem * p)
 {
-	__raw_writel((__force __u32)val, (__force void __iomem *)p);
+	__raw_writel((__force __u32) val, (__force void __iomem *)p);
 }
 
 static int
@@ -804,148 +814,6 @@
 	mb();
 }
 
-/*
- * Set of routines to get a new receive buffer.  Any buffer which
- * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
- * wdma restrictions. We also try to align any smaller allocation to
- * at least a 16 byte boundary for efficiency.  We assume the linux
- * memory allocator works by powers of 2, and will not return memory
- * smaller than 2KB which crosses a 4KB boundary.  If it does, we fall
- * back to allocating 2x as much space as required.
- *
- * We intend to replace large (>4KB) skb allocations by using
- * pages directly and building a fraglist in the near future.
- */
-
-static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev,
-						 int bytes)
-{
-	struct sk_buff *skb;
-	unsigned long data, roundup;
-
-	skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD);
-	if (skb == NULL)
-		return NULL;
-
-	/* Correct skb->truesize so that socket buffer
-	 * accounting is not confused the rounding we must
-	 * do to satisfy alignment constraints.
-	 */
-	skb->truesize -= 4096;
-
-	data = (unsigned long)(skb->data);
-	roundup = (-data) & (4095);
-	skb_reserve(skb, roundup);
-	return skb;
-}
-
-/* Allocate 2x as much space as required and use whichever portion
- * does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev,
-							unsigned int bytes)
-{
-	struct sk_buff *skb;
-	unsigned long data, boundary;
-
-	skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1);
-	if (unlikely(skb == NULL))
-		return NULL;
-
-	/* Correct skb->truesize so that socket buffer
-	 * accounting is not confused the rounding we must
-	 * do to satisfy alignment constraints.
-	 */
-	skb->truesize -= bytes + MXGEFW_PAD;
-
-	data = (unsigned long)(skb->data);
-	boundary = (data + 4095UL) & ~4095UL;
-	if ((boundary - data) >= (bytes + MXGEFW_PAD))
-		return skb;
-
-	skb_reserve(skb, boundary - data);
-	return skb;
-}
-
-/* Allocate just enough space, and verify that the allocated
- * space does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev,
-						   int bytes)
-{
-	struct sk_buff *skb;
-	unsigned long roundup, data, end;
-
-	skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD);
-	if (unlikely(skb == NULL))
-		return NULL;
-
-	/* Round allocated buffer to 16 byte boundary */
-	data = (unsigned long)(skb->data);
-	roundup = (-data) & 15UL;
-	skb_reserve(skb, roundup);
-	/* Verify that the data buffer does not cross a page boundary */
-	data = (unsigned long)(skb->data);
-	end = data + bytes + MXGEFW_PAD - 1;
-	if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) {
-		printk(KERN_NOTICE
-		       "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
-		myri10ge_skb_cross_4k = 1;
-		dev_kfree_skb_any(skb);
-		skb = myri10ge_alloc_small_safe(dev, bytes);
-	}
-	return skb;
-}
-
-static inline int
-myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp,
-		int bytes, int idx)
-{
-	struct net_device *dev = mgp->dev;
-	struct pci_dev *pdev = mgp->pdev;
-	struct sk_buff *skb;
-	dma_addr_t bus;
-	int len, retval = 0;
-
-	bytes += VLAN_HLEN;	/* account for 802.1q vlan tag */
-
-	if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
-		skb = myri10ge_alloc_big(dev, bytes);
-	else if (myri10ge_skb_cross_4k)
-		skb = myri10ge_alloc_small_safe(dev, bytes);
-	else
-		skb = myri10ge_alloc_small(dev, bytes);
-
-	if (unlikely(skb == NULL)) {
-		rx->alloc_fail++;
-		retval = -ENOBUFS;
-		goto done;
-	}
-
-	/* set len so that it only covers the area we
-	 * need mapped for DMA */
-	len = bytes + MXGEFW_PAD;
-
-	bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
-	rx->info[idx].skb = skb;
-	pci_unmap_addr_set(&rx->info[idx], bus, bus);
-	pci_unmap_len_set(&rx->info[idx], len, len);
-	rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus));
-	rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
-
-done:
-	/* copy 8 descriptors (64-bytes) to the mcp at a time */
-	if ((idx & 7) == 7) {
-		if (rx->wc_fifo == NULL)
-			myri10ge_submit_8rx(&rx->lanai[idx - 7],
-					    &rx->shadow[idx - 7]);
-		else {
-			mb();
-			myri10ge_pio_copy(rx->wc_fifo,
-					  &rx->shadow[idx - 7], 64);
-		}
-	}
-	return retval;
-}
-
 static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
 {
 	struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
@@ -958,40 +826,167 @@
 	}
 }
 
-static inline unsigned long
+static inline void
+myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
+		      struct skb_frag_struct *rx_frags, int len, int hlen)
+{
+	struct skb_frag_struct *skb_frags;
+
+	skb->len = skb->data_len = len;
+	skb->truesize = len + sizeof(struct sk_buff);
+	/* attach the page(s) */
+
+	skb_frags = skb_shinfo(skb)->frags;
+	while (len > 0) {
+		memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
+		len -= rx_frags->size;
+		skb_frags++;
+		rx_frags++;
+		skb_shinfo(skb)->nr_frags++;
+	}
+
+	/* pskb_may_pull is not available in irq context, but
+	 * skb_pull() (for ether_pad and eth_type_trans()) requires
+	 * the beginning of the packet in skb_headlen(), move it
+	 * manually */
+	memcpy(skb->data, va, hlen);
+	skb_shinfo(skb)->frags[0].page_offset += hlen;
+	skb_shinfo(skb)->frags[0].size -= hlen;
+	skb->data_len -= hlen;
+	skb->tail += hlen;
+	skb_pull(skb, MXGEFW_PAD);
+}
+
+static void
+myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+			int bytes, int watchdog)
+{
+	struct page *page;
+	int idx;
+
+	if (unlikely(rx->watchdog_needed && !watchdog))
+		return;
+
+	/* try to refill entire ring */
+	while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) {
+		idx = rx->fill_cnt & rx->mask;
+
+		if ((bytes < MYRI10GE_ALLOC_SIZE / 2) &&
+		    (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) {
+			/* we can use part of previous page */
+			get_page(rx->page);
+		} else {
+			/* we need a new page */
+			page =
+			    alloc_pages(GFP_ATOMIC | __GFP_COMP,
+					MYRI10GE_ALLOC_ORDER);
+			if (unlikely(page == NULL)) {
+				if (rx->fill_cnt - rx->cnt < 16)
+					rx->watchdog_needed = 1;
+				return;
+			}
+			rx->page = page;
+			rx->page_offset = 0;
+			rx->bus = pci_map_page(mgp->pdev, page, 0,
+					       MYRI10GE_ALLOC_SIZE,
+					       PCI_DMA_FROMDEVICE);
+		}
+		rx->info[idx].page = rx->page;
+		rx->info[idx].page_offset = rx->page_offset;
+		/* note that this is the address of the start of the
+		 * page */
+		pci_unmap_addr_set(&rx->info[idx], bus, rx->bus);
+		rx->shadow[idx].addr_low =
+		    htonl(MYRI10GE_LOWPART_TO_U32(rx->bus) + rx->page_offset);
+		rx->shadow[idx].addr_high =
+		    htonl(MYRI10GE_HIGHPART_TO_U32(rx->bus));
+
+		/* start next packet on a cacheline boundary */
+		rx->page_offset += SKB_DATA_ALIGN(bytes);
+		rx->fill_cnt++;
+
+		/* copy 8 descriptors to the firmware at a time */
+		if ((idx & 7) == 7) {
+			if (rx->wc_fifo == NULL)
+				myri10ge_submit_8rx(&rx->lanai[idx - 7],
+						    &rx->shadow[idx - 7]);
+			else {
+				mb();
+				myri10ge_pio_copy(rx->wc_fifo,
+						  &rx->shadow[idx - 7], 64);
+			}
+		}
+	}
+}
+
+static inline void
+myri10ge_unmap_rx_page(struct pci_dev *pdev,
+		       struct myri10ge_rx_buffer_state *info, int bytes)
+{
+	/* unmap the recvd page if we're the only or last user of it */
+	if (bytes >= MYRI10GE_ALLOC_SIZE / 2 ||
+	    (info->page_offset + 2 * bytes) > MYRI10GE_ALLOC_SIZE) {
+		pci_unmap_page(pdev, (pci_unmap_addr(info, bus)
+				      & ~(MYRI10GE_ALLOC_SIZE - 1)),
+			       MYRI10GE_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+	}
+}
+
+#define MYRI10GE_HLEN 64	/* The number of bytes to copy from a
+				 * page into an skb */
+
+static inline int
 myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
 		 int bytes, int len, __wsum csum)
 {
-	dma_addr_t bus;
 	struct sk_buff *skb;
-	int idx, unmap_len;
+	struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
+	int i, idx, hlen, remainder;
+	struct pci_dev *pdev = mgp->pdev;
+	struct net_device *dev = mgp->dev;
+	u8 *va;
 
+	len += MXGEFW_PAD;
 	idx = rx->cnt & rx->mask;
-	rx->cnt++;
+	va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
+	prefetch(va);
+	/* Fill skb_frag_struct(s) with data from our receive */
+	for (i = 0, remainder = len; remainder > 0; i++) {
+		myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
+		rx_frags[i].page = rx->info[idx].page;
+		rx_frags[i].page_offset = rx->info[idx].page_offset;
+		if (remainder < MYRI10GE_ALLOC_SIZE)
+			rx_frags[i].size = remainder;
+		else
+			rx_frags[i].size = MYRI10GE_ALLOC_SIZE;
+		rx->cnt++;
+		idx = rx->cnt & rx->mask;
+		remainder -= MYRI10GE_ALLOC_SIZE;
+	}
 
-	/* save a pointer to the received skb */
-	skb = rx->info[idx].skb;
-	bus = pci_unmap_addr(&rx->info[idx], bus);
-	unmap_len = pci_unmap_len(&rx->info[idx], len);
+	hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
 
-	/* try to replace the received skb */
-	if (myri10ge_getbuf(rx, mgp, bytes, idx)) {
-		/* drop the frame -- the old skbuf is re-cycled */
-		mgp->stats.rx_dropped += 1;
+	/* allocate an skb to attach the page(s) to. */
+
+	skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
+	if (unlikely(skb == NULL)) {
+		mgp->stats.rx_dropped++;
+		do {
+			i--;
+			put_page(rx_frags[i].page);
+		} while (i != 0);
 		return 0;
 	}
 
-	/* unmap the recvd skb */
-	pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE);
+	/* Attach the pages to the skb, and trim off any padding */
+	myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
+	if (skb_shinfo(skb)->frags[0].size <= 0) {
+		put_page(skb_shinfo(skb)->frags[0].page);
+		skb_shinfo(skb)->nr_frags = 0;
+	}
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->dev = dev;
 
-	/* mcp implicitly skips 1st bytes so that packet is properly
-	 * aligned */
-	skb_reserve(skb, MXGEFW_PAD);
-
-	/* set the length of the frame */
-	skb_put(skb, len);
-
-	skb->protocol = eth_type_trans(skb, mgp->dev);
 	if (mgp->csum_flag) {
 		if ((skb->protocol == htons(ETH_P_IP)) ||
 		    (skb->protocol == htons(ETH_P_IPV6))) {
@@ -1000,9 +995,8 @@
 		} else
 			myri10ge_vlan_ip_csum(skb, csum);
 	}
-
 	netif_receive_skb(skb);
-	mgp->dev->last_rx = jiffies;
+	dev->last_rx = jiffies;
 	return 1;
 }
 
@@ -1079,7 +1073,7 @@
 						 length, checksum);
 		else
 			rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big,
-						 mgp->dev->mtu + ETH_HLEN,
+						 mgp->big_bytes,
 						 length, checksum);
 		rx_packets += rx_ok;
 		rx_bytes += rx_ok * (unsigned long)length;
@@ -1094,6 +1088,14 @@
 	rx_done->cnt = cnt;
 	mgp->stats.rx_packets += rx_packets;
 	mgp->stats.rx_bytes += rx_bytes;
+
+	/* restock receive rings if needed */
+	if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh)
+		myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+					mgp->small_bytes + MXGEFW_PAD, 0);
+	if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh)
+		myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
+
 }
 
 static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
@@ -1484,56 +1486,48 @@
 		goto abort_with_rx_small_info;
 
 	/* Fill the receive rings */
+	mgp->rx_big.cnt = 0;
+	mgp->rx_small.cnt = 0;
+	mgp->rx_big.fill_cnt = 0;
+	mgp->rx_small.fill_cnt = 0;
+	mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE;
+	mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE;
+	mgp->rx_small.watchdog_needed = 0;
+	mgp->rx_big.watchdog_needed = 0;
+	myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+				mgp->small_bytes + MXGEFW_PAD, 0);
 
-	for (i = 0; i <= mgp->rx_small.mask; i++) {
-		status = myri10ge_getbuf(&mgp->rx_small, mgp,
-					 mgp->small_bytes, i);
-		if (status) {
-			printk(KERN_ERR
-			       "myri10ge: %s: alloced only %d small bufs\n",
-			       dev->name, i);
-			goto abort_with_rx_small_ring;
-		}
+	if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) {
+		printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n",
+		       dev->name, mgp->rx_small.fill_cnt);
+		goto abort_with_rx_small_ring;
 	}
 
-	for (i = 0; i <= mgp->rx_big.mask; i++) {
-		status =
-		    myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i);
-		if (status) {
-			printk(KERN_ERR
-			       "myri10ge: %s: alloced only %d big bufs\n",
-			       dev->name, i);
-			goto abort_with_rx_big_ring;
-		}
+	myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
+	if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) {
+		printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n",
+		       dev->name, mgp->rx_big.fill_cnt);
+		goto abort_with_rx_big_ring;
 	}
 
 	return 0;
 
 abort_with_rx_big_ring:
-	for (i = 0; i <= mgp->rx_big.mask; i++) {
-		if (mgp->rx_big.info[i].skb != NULL)
-			dev_kfree_skb_any(mgp->rx_big.info[i].skb);
-		if (pci_unmap_len(&mgp->rx_big.info[i], len))
-			pci_unmap_single(mgp->pdev,
-					 pci_unmap_addr(&mgp->rx_big.info[i],
-							bus),
-					 pci_unmap_len(&mgp->rx_big.info[i],
-						       len),
-					 PCI_DMA_FROMDEVICE);
+	for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) {
+		int idx = i & mgp->rx_big.mask;
+		myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx],
+				       mgp->big_bytes);
+		put_page(mgp->rx_big.info[idx].page);
 	}
 
 abort_with_rx_small_ring:
-	for (i = 0; i <= mgp->rx_small.mask; i++) {
-		if (mgp->rx_small.info[i].skb != NULL)
-			dev_kfree_skb_any(mgp->rx_small.info[i].skb);
-		if (pci_unmap_len(&mgp->rx_small.info[i], len))
-			pci_unmap_single(mgp->pdev,
-					 pci_unmap_addr(&mgp->rx_small.info[i],
-							bus),
-					 pci_unmap_len(&mgp->rx_small.info[i],
-						       len),
-					 PCI_DMA_FROMDEVICE);
+	for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) {
+		int idx = i & mgp->rx_small.mask;
+		myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx],
+				       mgp->small_bytes + MXGEFW_PAD);
+		put_page(mgp->rx_small.info[idx].page);
 	}
+
 	kfree(mgp->rx_big.info);
 
 abort_with_rx_small_info:
@@ -1566,30 +1560,24 @@
 
 	mgp = netdev_priv(dev);
 
-	for (i = 0; i <= mgp->rx_big.mask; i++) {
-		if (mgp->rx_big.info[i].skb != NULL)
-			dev_kfree_skb_any(mgp->rx_big.info[i].skb);
-		if (pci_unmap_len(&mgp->rx_big.info[i], len))
-			pci_unmap_single(mgp->pdev,
-					 pci_unmap_addr(&mgp->rx_big.info[i],
-							bus),
-					 pci_unmap_len(&mgp->rx_big.info[i],
-						       len),
-					 PCI_DMA_FROMDEVICE);
+	for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) {
+		idx = i & mgp->rx_big.mask;
+		if (i == mgp->rx_big.fill_cnt - 1)
+			mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE;
+		myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx],
+				       mgp->big_bytes);
+		put_page(mgp->rx_big.info[idx].page);
 	}
 
-	for (i = 0; i <= mgp->rx_small.mask; i++) {
-		if (mgp->rx_small.info[i].skb != NULL)
-			dev_kfree_skb_any(mgp->rx_small.info[i].skb);
-		if (pci_unmap_len(&mgp->rx_small.info[i], len))
-			pci_unmap_single(mgp->pdev,
-					 pci_unmap_addr(&mgp->rx_small.info[i],
-							bus),
-					 pci_unmap_len(&mgp->rx_small.info[i],
-						       len),
-					 PCI_DMA_FROMDEVICE);
+	for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) {
+		idx = i & mgp->rx_small.mask;
+		if (i == mgp->rx_small.fill_cnt - 1)
+			mgp->rx_small.info[idx].page_offset =
+			    MYRI10GE_ALLOC_SIZE;
+		myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx],
+				       mgp->small_bytes + MXGEFW_PAD);
+		put_page(mgp->rx_small.info[idx].page);
 	}
-
 	tx = &mgp->tx;
 	while (tx->done != tx->req) {
 		idx = tx->done & tx->mask;
@@ -1657,19 +1645,18 @@
 	 */
 
 	if (dev->mtu <= ETH_DATA_LEN)
-		mgp->small_bytes = 128;	/* enough for a TCP header */
+		/* enough for a TCP header */
+		mgp->small_bytes = (128 > SMP_CACHE_BYTES)
+		    ? (128 - MXGEFW_PAD)
+		    : (SMP_CACHE_BYTES - MXGEFW_PAD);
 	else
-		mgp->small_bytes = ETH_FRAME_LEN;	/* enough for an ETH_DATA_LEN frame */
+		/* enough for a vlan encapsulated ETH_DATA_LEN frame */
+		mgp->small_bytes = VLAN_ETH_FRAME_LEN;
 
 	/* Override the small buffer size? */
 	if (myri10ge_small_bytes > 0)
 		mgp->small_bytes = myri10ge_small_bytes;
 
-	/* If the user sets an obscenely small MTU, adjust the small
-	 * bytes down to nearly nothing */
-	if (mgp->small_bytes >= (dev->mtu + ETH_HLEN))
-		mgp->small_bytes = 64;
-
 	/* get the lanai pointers to the send and receive rings */
 
 	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
@@ -1705,17 +1692,23 @@
 		mgp->rx_big.wc_fifo = NULL;
 	}
 
-	status = myri10ge_allocate_rings(dev);
-	if (status != 0)
-		goto abort_with_nothing;
-
 	/* Firmware needs the big buff size as a power of 2.  Lie and
 	 * tell him the buffer is larger, because we only use 1
 	 * buffer/pkt, and the mtu will prevent overruns.
 	 */
-	big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD;
-	while ((big_pow2 & (big_pow2 - 1)) != 0)
-		big_pow2++;
+	big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
+	if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
+		while ((big_pow2 & (big_pow2 - 1)) != 0)
+			big_pow2++;
+		mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
+	} else {
+		big_pow2 = MYRI10GE_ALLOC_SIZE;
+		mgp->big_bytes = big_pow2;
+	}
+
+	status = myri10ge_allocate_rings(dev);
+	if (status != 0)
+		goto abort_with_nothing;
 
 	/* now give firmware buffers sizes, and MTU */
 	cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
@@ -2206,7 +2199,7 @@
 	struct myri10ge_cmd cmd;
 	struct myri10ge_priv *mgp;
 	struct dev_mc_list *mc_list;
-	__be32 data[2] = {0, 0};
+	__be32 data[2] = { 0, 0 };
 	int err;
 
 	mgp = netdev_priv(dev);
@@ -2625,7 +2618,7 @@
 static void myri10ge_watchdog(struct work_struct *work)
 {
 	struct myri10ge_priv *mgp =
-		container_of(work, struct myri10ge_priv, watchdog_work);
+	    container_of(work, struct myri10ge_priv, watchdog_work);
 	u32 reboot;
 	int status;
 	u16 cmd, vendor;
@@ -2698,6 +2691,21 @@
 	struct myri10ge_priv *mgp;
 
 	mgp = (struct myri10ge_priv *)arg;
+
+	if (mgp->rx_small.watchdog_needed) {
+		myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+					mgp->small_bytes + MXGEFW_PAD, 1);
+		if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >=
+		    myri10ge_fill_thresh)
+			mgp->rx_small.watchdog_needed = 0;
+	}
+	if (mgp->rx_big.watchdog_needed) {
+		myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1);
+		if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >=
+		    myri10ge_fill_thresh)
+			mgp->rx_big.watchdog_needed = 0;
+	}
+
 	if (mgp->tx.req != mgp->tx.done &&
 	    mgp->tx.done == mgp->watchdog_tx_done &&
 	    mgp->watchdog_tx_req != mgp->watchdog_tx_done)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 9367c57..d2767e6 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -362,96 +362,6 @@
 
 #define SMC_IRQ_FLAGS		(0)
 
-#elif	defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT	1
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	1
-#define SMC_NOWAIT		1
-
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
-
-#define SMC_IRQ_FLAGS		(0)
-
-#elif	defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT	1
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	1
-#define SMC_NOWAIT		1
-
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
-
-#define SMC_IRQ_FLAGS		(0)
-
-#elif	defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT	1
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	1
-#define SMC_NOWAIT		1
-
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
-
-#define SMC_IRQ_FLAGS		(0)
-
-#elif	defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT	1
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	1
-#define SMC_NOWAIT		1
-
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
-
-#define SMC_IRQ_FLAGS		(0)
-
-#elif	defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT	1
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	1
-#define SMC_NOWAIT		1
-
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
-
-#define SMC_IRQ_FLAGS		(0)
-
 #else
 
 #define SMC_CAN_USE_8BIT	1
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 1f05511..8243150 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -194,9 +194,9 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(ugeth_lock, flags);
+	spin_lock_irqsave(&ugeth_lock, flags);
 	list_add_tail(node, lh);
-	spin_unlock_irqrestore(ugeth_lock, flags);
+	spin_unlock_irqrestore(&ugeth_lock, flags);
 }
 #endif /* CONFIG_UGETH_FILTERING */
 
@@ -204,14 +204,14 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(ugeth_lock, flags);
+	spin_lock_irqsave(&ugeth_lock, flags);
 	if (!list_empty(lh)) {
 		struct list_head *node = lh->next;
 		list_del(node);
-		spin_unlock_irqrestore(ugeth_lock, flags);
+		spin_unlock_irqrestore(&ugeth_lock, flags);
 		return node;
 	} else {
-		spin_unlock_irqrestore(ugeth_lock, flags);
+		spin_unlock_irqrestore(&ugeth_lock, flags);
 		return NULL;
 	}
 }
@@ -1852,6 +1852,8 @@
 	mii_info->mdio_read = &read_phy_reg;
 	mii_info->mdio_write = &write_phy_reg;
 
+	spin_lock_init(&mii_info->mdio_lock);
+
 	ugeth->mii_info = mii_info;
 
 	spin_lock_irq(&ugeth->lock);
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index d5ab9cf..21f76f5 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -382,7 +382,7 @@
 
 # Wan router core.
 config WAN_ROUTER_DRIVERS
-	bool "WAN router drivers"
+	tristate "WAN router drivers"
 	depends on WAN && WAN_ROUTER
 	---help---
 	  Connect LAN to WAN via Linux box.
@@ -393,7 +393,8 @@
 	  <file:Documentation/networking/wan-router.txt>.
 
 	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
+	  kernel except for how subordinate drivers may be built:
+	  saying N will just cause the configurator to skip all
 	  the questions about WAN router drivers.
 
 	  If unsure, say N.
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index b52d547..8433eb7 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1 +1,2 @@
 obj-y += system-bus.o
+obj-$(CONFIG_PS3_VUART) += vuart.o
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
new file mode 100644
index 0000000..6974f65
--- /dev/null
+++ b/drivers/ps3/vuart.c
@@ -0,0 +1,965 @@
+/*
+ *  PS3 virtual uart
+ *
+ *  Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *  Copyright 2006 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/interrupt.h>
+#include <asm/ps3.h>
+
+#include <asm/lv1call.h>
+#include <asm/bitops.h>
+
+#include "vuart.h"
+
+MODULE_AUTHOR("Sony Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ps3 vuart");
+
+/**
+ * vuart - An inter-partition data link service.
+ *  port 0: PS3 AV Settings.
+ *  port 2: PS3 System Manager.
+ *
+ * The vuart provides a bi-directional byte stream data link between logical
+ * partitions.  Its primary role is as a communications link between the guest
+ * OS and the system policy module.  The current HV does not support any
+ * connections other than those listed.
+ */
+
+enum {PORT_COUNT = 3,};
+
+enum vuart_param {
+	PARAM_TX_TRIGGER = 0,
+	PARAM_RX_TRIGGER = 1,
+	PARAM_INTERRUPT_MASK = 2,
+	PARAM_RX_BUF_SIZE = 3, /* read only */
+	PARAM_RX_BYTES = 4, /* read only */
+	PARAM_TX_BUF_SIZE = 5, /* read only */
+	PARAM_TX_BYTES = 6, /* read only */
+	PARAM_INTERRUPT_STATUS = 7, /* read only */
+};
+
+enum vuart_interrupt_bit {
+	INTERRUPT_BIT_TX = 0,
+	INTERRUPT_BIT_RX = 1,
+	INTERRUPT_BIT_DISCONNECT = 2,
+};
+
+enum vuart_interrupt_mask {
+	INTERRUPT_MASK_TX = 1,
+	INTERRUPT_MASK_RX = 2,
+	INTERRUPT_MASK_DISCONNECT = 4,
+};
+
+/**
+ * struct ports_bmp - bitmap indicating ports needing service.
+ *
+ * A 256 bit read only bitmap indicating ports needing service.  Do not write
+ * to these bits.  Must not cross a page boundary.
+ */
+
+struct ports_bmp {
+	u64 status;
+	u64 unused[3];
+} __attribute__ ((aligned (32)));
+
+/* redefine dev_dbg to do a syntax check */
+
+#if !defined(DEBUG)
+#undef dev_dbg
+static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
+	const struct device *_dev, const char *fmt, ...) {return 0;}
+#endif
+
+#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
+static void __attribute__ ((unused)) _dump_ports_bmp(
+	const struct ports_bmp* bmp, const char* func, int line)
+{
+	pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
+}
+
+static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
+	unsigned int *port_number)
+{
+	switch(match_id) {
+	case PS3_MATCH_ID_AV_SETTINGS:
+		*port_number = 0;
+		return 0;
+	case PS3_MATCH_ID_SYSTEM_MANAGER:
+		*port_number = 2;
+		return 0;
+	default:
+		WARN_ON(1);
+		*port_number = UINT_MAX;
+		return -EINVAL;
+	};
+}
+
+#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
+static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+	const char* func, int line)
+{
+#if defined(DEBUG)
+	static const char *strings[] = {
+		"tx_trigger      ",
+		"rx_trigger      ",
+		"interrupt_mask  ",
+		"rx_buf_size     ",
+		"rx_bytes        ",
+		"tx_buf_size     ",
+		"tx_bytes        ",
+		"interrupt_status",
+	};
+	int result;
+	unsigned int i;
+	u64 value;
+
+	for (i = 0; i < ARRAY_SIZE(strings); i++) {
+		result = lv1_get_virtual_uart_param(port_number, i, &value);
+
+		if (result) {
+			pr_debug("%s:%d: port_%u: %s failed: %s\n", func, line,
+				port_number, strings[i], ps3_result(result));
+			continue;
+		}
+		pr_debug("%s:%d: port_%u: %s = %lxh\n",
+			func, line, port_number, strings[i], value);
+	}
+#endif
+}
+
+struct vuart_triggers {
+	unsigned long rx;
+	unsigned long tx;
+};
+
+int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+	struct vuart_triggers *trig)
+{
+	int result;
+	unsigned long size;
+	unsigned long val;
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
+		PARAM_TX_TRIGGER, &trig->tx);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
+		PARAM_RX_BUF_SIZE, &size);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
+		PARAM_RX_TRIGGER, &val);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	trig->rx = size - val;
+
+	dev_dbg(&dev->core, "%s:%d: tx %lxh, rx %lxh\n", __func__, __LINE__,
+		trig->tx, trig->rx);
+
+	return result;
+}
+
+int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+	unsigned int rx)
+{
+	int result;
+	unsigned long size;
+
+	result = lv1_set_virtual_uart_param(dev->port_number,
+		PARAM_TX_TRIGGER, tx);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
+		PARAM_RX_BUF_SIZE, &size);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	result = lv1_set_virtual_uart_param(dev->port_number,
+		PARAM_RX_TRIGGER, size - rx);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	dev_dbg(&dev->core, "%s:%d: tx %xh, rx %xh\n", __func__, __LINE__,
+		tx, rx);
+
+	return result;
+}
+
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+	unsigned long *bytes_waiting)
+{
+	int result = lv1_get_virtual_uart_param(dev->port_number,
+		PARAM_RX_BYTES, bytes_waiting);
+
+	if (result)
+		dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+
+	dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__,
+		*bytes_waiting);
+	return result;
+}
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+	unsigned long mask)
+{
+	int result;
+
+	dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
+
+	dev->interrupt_mask = mask;
+
+	result = lv1_set_virtual_uart_param(dev->port_number,
+		PARAM_INTERRUPT_MASK, dev->interrupt_mask);
+
+	if (result)
+		dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+
+	return result;
+}
+
+static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev,
+	unsigned long *status)
+{
+	int result = lv1_get_virtual_uart_param(dev->port_number,
+		PARAM_INTERRUPT_STATUS, status);
+
+	if (result)
+		dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+
+	dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
+		__func__, __LINE__, dev->interrupt_mask, *status,
+		dev->interrupt_mask & *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
+		| 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
+		| 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
+		| 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
+		& ~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
+		& ~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
+		& ~INTERRUPT_MASK_DISCONNECT) : 0;
+}
+
+/**
+ * ps3_vuart_raw_write - Low level write helper.
+ *
+ * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
+ */
+
+static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+	const void* buf, unsigned int bytes, unsigned long *bytes_written)
+{
+	int result;
+
+	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
+
+	result = lv1_write_virtual_uart(dev->port_number,
+		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: lv1_write_virtual_uart failed: "
+			"%s\n", __func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	dev->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);
+
+	return result;
+}
+
+/**
+ * ps3_vuart_raw_read - Low level read helper.
+ *
+ * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
+ */
+
+static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+	unsigned int bytes, unsigned long *bytes_read)
+{
+	int result;
+
+	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
+
+	result = lv1_read_virtual_uart(dev->port_number,
+		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: lv1_read_virtual_uart failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		return result;
+	}
+
+	dev->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);
+
+	return result;
+}
+
+/**
+ * struct list_buffer - An element for a port device fifo buffer list.
+ */
+
+struct list_buffer {
+	struct list_head link;
+	const unsigned char *head;
+	const unsigned char *tail;
+	unsigned long dbg_number;
+	unsigned char data[];
+};
+
+/**
+ * ps3_vuart_write - the entry point for writing data to a port
+ *
+ * If the port is idle on entry as much of the incoming data is written to
+ * the port as the port will accept.  Otherwise a list buffer is created
+ * and any remaning incoming data is copied to that buffer.  The buffer is
+ * then enqueued for transmision via the transmit interrupt.
+ */
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+	unsigned int bytes)
+{
+	static unsigned long dbg_number;
+	int result;
+	unsigned long flags;
+	struct list_buffer *lb;
+
+	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
+		bytes, bytes);
+
+	spin_lock_irqsave(&dev->tx_list.lock, flags);
+
+	if (list_empty(&dev->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);
+
+		if (result) {
+			dev_dbg(&dev->core,
+				"%s:%d: ps3_vuart_raw_write failed\n",
+				__func__, __LINE__);
+			return result;
+		}
+
+		if (bytes_written == bytes) {
+			dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n",
+				__func__, __LINE__, bytes);
+			return 0;
+		}
+
+		bytes -= bytes_written;
+		buf += bytes_written;
+	} else
+		spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
+
+	if (!lb) {
+		return -ENOMEM;
+	}
+
+	memcpy(lb->data, buf, bytes);
+	lb->head = lb->data;
+	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);
+	ps3_vuart_enable_interrupt_tx(dev);
+	spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
+		__func__, __LINE__, lb->dbg_number, bytes);
+
+	return 0;
+}
+
+/**
+ * ps3_vuart_read - the entry point for reading data from a port
+ *
+ * If enough bytes to satisfy the request are held in the buffer list those
+ * bytes are dequeued and copied to the caller's buffer.  Emptied list buffers
+ * are retiered.  If the request cannot be statified by bytes held in the list
+ * buffers -EAGAIN is returned.
+ */
+
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+	unsigned int bytes)
+{
+	unsigned long flags;
+	struct list_buffer *lb, *n;
+	unsigned long bytes_read;
+
+	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
+		bytes, bytes);
+
+	spin_lock_irqsave(&dev->rx_list.lock, flags);
+
+	if (dev->rx_list.bytes_held < bytes) {
+		spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+		dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+			__func__, __LINE__, bytes - dev->rx_list.bytes_held);
+		return -EAGAIN;
+	}
+
+	list_for_each_entry_safe(lb, n, &dev->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;
+
+		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);
+			return 0;
+		}
+
+		dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
+			lb->dbg_number);
+
+		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);
+
+	return 0;
+}
+
+/**
+ * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
+ *
+ * Services the transmit interrupt for the port.  Writes as much data from the
+ * buffer list as the port will accept.  Retires any emptied list buffers and
+ * adjusts the final list buffer state for a partial write.
+ */
+
+static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+	int result = 0;
+	unsigned long flags;
+	struct list_buffer *lb, *n;
+	unsigned long bytes_total = 0;
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	spin_lock_irqsave(&dev->tx_list.lock, flags);
+
+	list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) {
+
+		unsigned long bytes_written;
+
+		result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head,
+			&bytes_written);
+
+		if (result) {
+			dev_dbg(&dev->core,
+				"%s:%d: ps3_vuart_raw_write failed\n",
+				__func__, __LINE__);
+			break;
+		}
+
+		bytes_total += bytes_written;
+
+		if (bytes_written < lb->tail - lb->head) {
+			lb->head += bytes_written;
+			dev_dbg(&dev->core,
+				"%s:%d cleared buf_%lu, %lxh bytes\n",
+				__func__, __LINE__, lb->dbg_number,
+				bytes_written);
+			goto port_full;
+		}
+
+		dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
+			lb->dbg_number);
+
+		list_del(&lb->link);
+		kfree(lb);
+	}
+
+	ps3_vuart_disable_interrupt_tx(dev);
+port_full:
+	spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+	dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
+		__func__, __LINE__, bytes_total);
+	return result;
+}
+
+/**
+ * ps3_vuart_handle_interrupt_rx - third stage receive interrupt handler
+ *
+ * Services the receive interrupt for the port.  Creates a list buffer and
+ * copies all waiting port data to that buffer and enqueues the buffer in the
+ * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
+ */
+
+static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+	static unsigned long dbg_number;
+	int result = 0;
+	unsigned long flags;
+	struct list_buffer *lb;
+	unsigned long bytes;
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+
+	if (result)
+		return -EIO;
+
+	BUG_ON(!bytes);
+
+	/* add some extra space for recently arrived data */
+
+	bytes += 128;
+
+	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+	if (!lb)
+		return -ENOMEM;
+
+	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+	lb->head = lb->data;
+	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);
+
+	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n",
+		__func__, __LINE__, lb->dbg_number, bytes);
+
+	return 0;
+}
+
+static int ps3_vuart_handle_interrupt_disconnect(
+	struct ps3_vuart_port_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+	BUG_ON("no support");
+	return -1;
+}
+
+/**
+ * ps3_vuart_handle_port_interrupt - second stage interrupt handler
+ *
+ * Services any pending interrupt types for the port.  Passes control to the
+ * third stage type specific interrupt handler.  Returns control to the first
+ * stage handler after one iteration.
+ */
+
+static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+{
+	int result;
+	unsigned long status;
+
+	result = ps3_vuart_get_interrupt_mask(dev, &status);
+
+	if (result)
+		return result;
+
+	dev_dbg(&dev->core, "%s:%d: status: %lxh\n", __func__, __LINE__,
+		status);
+
+	if (status & INTERRUPT_MASK_DISCONNECT) {
+		dev->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++;
+		result = ps3_vuart_handle_interrupt_tx(dev);
+		if (result)
+			ps3_vuart_disable_interrupt_tx(dev);
+	}
+
+	if (status & INTERRUPT_MASK_RX) {
+		dev->stats.rx_interrupts++;
+		result = ps3_vuart_handle_interrupt_rx(dev);
+		if (result)
+			ps3_vuart_disable_interrupt_rx(dev);
+	}
+
+	return 0;
+}
+
+struct vuart_private {
+	unsigned int in_use;
+	unsigned int virq;
+	struct ps3_vuart_port_device *devices[PORT_COUNT];
+	const struct ports_bmp bmp;
+};
+
+/**
+ * ps3_vuart_irq_handler - first stage interrupt handler
+ *
+ * Loops finding any interrupting port and its associated instance data.
+ * Passes control to the second stage port specific interrupt handler.  Loops
+ * until all outstanding interrupts are serviced.
+ */
+
+static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
+{
+	struct vuart_private *private;
+
+	BUG_ON(!_private);
+	private = (struct vuart_private *)_private;
+
+	while (1) {
+		unsigned int port;
+
+		dump_ports_bmp(&private->bmp);
+
+		port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status);
+
+		if (port == BITS_PER_LONG)
+			break;
+
+		BUG_ON(port >= PORT_COUNT);
+		BUG_ON(!private->devices[port]);
+
+		ps3_vuart_handle_port_interrupt(private->devices[port]);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+{
+	int result;
+	struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
+	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+
+	result = dev->match_id == drv->match_id;
+
+	dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
+		__LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
+		drv->core.name, (result ? "match" : "miss"));
+
+	return result;
+}
+
+static struct vuart_private vuart_private;
+
+static int ps3_vuart_probe(struct device *_dev)
+{
+	int result;
+	unsigned long tmp;
+	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\n", __func__, __LINE__);
+
+	BUG_ON(!drv);
+
+	result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
+			__func__, __LINE__, dev->match_id);
+		result = -EINVAL;
+		goto fail_match;
+	}
+
+	if (vuart_private.devices[dev->port_number]) {
+		dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
+			__LINE__, dev->port_number);
+		result = -EBUSY;
+		goto fail_match;
+	}
+
+	vuart_private.devices[dev->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);
+
+	vuart_private.in_use++;
+	if (vuart_private.in_use == 1) {
+		result = ps3_alloc_vuart_irq((void*)&vuart_private.bmp.status,
+			&vuart_private.virq);
+
+		if (result) {
+			dev_dbg(&dev->core,
+				"%s:%d: ps3_alloc_vuart_irq failed (%d)\n",
+				__func__, __LINE__, result);
+			result = -EPERM;
+			goto fail_alloc_irq;
+		}
+
+		result = request_irq(vuart_private.virq, ps3_vuart_irq_handler,
+			IRQF_DISABLED, "vuart", &vuart_private);
+
+		if (result) {
+			dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
+				__func__, __LINE__, result);
+			goto fail_request_irq;
+		}
+	}
+
+	ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
+
+	/* clear stale pending interrupts */
+	ps3_vuart_get_interrupt_mask(dev, &tmp);
+
+	ps3_vuart_set_triggers(dev, 1, 1);
+
+	if (drv->probe)
+		result = drv->probe(dev);
+	else {
+		result = 0;
+		dev_info(&dev->core, "%s:%d: no probe method\n", __func__,
+			__LINE__);
+	}
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
+			__func__, __LINE__);
+		goto fail_probe;
+	}
+
+	return result;
+
+fail_probe:
+fail_request_irq:
+	vuart_private.in_use--;
+	if (!vuart_private.in_use) {
+		ps3_free_vuart_irq(vuart_private.virq);
+		vuart_private.virq = NO_IRQ;
+	}
+fail_alloc_irq:
+fail_match:
+	dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+	return result;
+}
+
+static int ps3_vuart_remove(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);
+
+	BUG_ON(vuart_private.in_use < 1);
+
+	if (drv->remove)
+		drv->remove(dev);
+	else
+		dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
+			__LINE__, dev->core.bus_id);
+
+	vuart_private.in_use--;
+
+	if (!vuart_private.in_use) {
+		free_irq(vuart_private.virq, &vuart_private);
+		ps3_free_vuart_irq(vuart_private.virq);
+		vuart_private.virq = NO_IRQ;
+	}
+	return 0;
+}
+
+/**
+ * ps3_vuart - The vuart instance.
+ *
+ * The vuart is managed as a bus that port devices connect to.
+ */
+
+struct bus_type ps3_vuart = {
+        .name = "ps3_vuart",
+	.match = ps3_vuart_match,
+	.probe = ps3_vuart_probe,
+	.remove = ps3_vuart_remove,
+};
+
+int __init ps3_vuart_init(void)
+{
+	int result;
+
+	pr_debug("%s:%d:\n", __func__, __LINE__);
+	result = bus_register(&ps3_vuart);
+	BUG_ON(result);
+	return result;
+}
+
+void __exit ps3_vuart_exit(void)
+{
+	pr_debug("%s:%d:\n", __func__, __LINE__);
+	bus_unregister(&ps3_vuart);
+}
+
+core_initcall(ps3_vuart_init);
+module_exit(ps3_vuart_exit);
+
+/**
+ * ps3_vuart_port_release_device - Remove a vuart port device.
+ */
+
+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));
+#endif
+	kfree(dev);
+}
+
+/**
+ * ps3_vuart_port_device_register - Add a vuart port device.
+ */
+
+int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
+{
+	int result;
+	static unsigned int dev_count = 1;
+
+	dev->core.parent = NULL;
+	dev->core.bus = &ps3_vuart;
+	dev->core.release = ps3_vuart_port_release_device;
+
+	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
+		dev_count++);
+
+	dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
+
+	result = device_register(&dev->core);
+
+	return result;
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
+
+/**
+ * ps3_vuart_port_driver_register - Add a vuart port device driver.
+ */
+
+int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
+{
+	int result;
+
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
+	drv->core.bus = &ps3_vuart;
+	result = driver_register(&drv->core);
+	return result;
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
+
+/**
+ * ps3_vuart_port_driver_unregister - Remove a vuart port device driver.
+ */
+
+void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
+{
+	driver_unregister(&drv->core);
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
new file mode 100644
index 0000000..28fd89f
--- /dev/null
+++ b/drivers/ps3/vuart.h
@@ -0,0 +1,94 @@
+/*
+ *  PS3 virtual uart
+ *
+ *  Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *  Copyright 2006 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
+ */
+
+#if !defined(_PS3_VUART_H)
+#define _PS3_VUART_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_port_device - a device on a vuart port
+ */
+
+struct ps3_vuart_port_device {
+	enum ps3_match_id match_id;
+	struct device core;
+
+	/* private driver variables */
+	unsigned int port_number;
+	unsigned long 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_port_driver - a driver for a device on a vuart port
+ */
+
+struct ps3_vuart_port_driver {
+	enum ps3_match_id match_id;
+	struct device_driver core;
+	int (*probe)(struct ps3_vuart_port_device *);
+	int (*remove)(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);
+	/* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
+	/* int (*resume)(struct ps3_vuart_port_device *); */
+};
+
+int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
+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)
+{
+	return container_of(_drv, struct ps3_vuart_port_driver, core);
+}
+static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
+	struct device *_dev)
+{
+	return container_of(_dev, struct ps3_vuart_port_device, core);
+}
+
+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);
+
+#endif
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 143302a..72ba1a7 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -2,6 +2,7 @@
  * SuperH On-Chip RTC Support
  *
  * Copyright (C) 2006  Paul Mundt
+ * Copyright (C) 2006  Jamie Lenehan
  *
  * Based on the old arch/sh/kernel/cpu/rtc.c by:
  *
@@ -21,7 +22,10 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
+
+#define DRV_NAME	"sh-rtc"
+#define DRV_VERSION	"0.1.2"
 
 #ifdef CONFIG_CPU_SH3
 #define rtc_reg_size		sizeof(u16)
@@ -33,22 +37,26 @@
 
 #define RTC_REG(r)	((r) * rtc_reg_size)
 
-#define R64CNT  	RTC_REG(0)
-#define RSECCNT 	RTC_REG(1)
-#define RMINCNT 	RTC_REG(2)
-#define RHRCNT  	RTC_REG(3)
-#define RWKCNT  	RTC_REG(4)
-#define RDAYCNT 	RTC_REG(5)
-#define RMONCNT 	RTC_REG(6)
-#define RYRCNT  	RTC_REG(7)
-#define RSECAR  	RTC_REG(8)
-#define RMINAR  	RTC_REG(9)
-#define RHRAR   	RTC_REG(10)
-#define RWKAR   	RTC_REG(11)
-#define RDAYAR  	RTC_REG(12)
-#define RMONAR  	RTC_REG(13)
-#define RCR1    	RTC_REG(14)
-#define RCR2    	RTC_REG(15)
+#define R64CNT		RTC_REG(0)
+
+#define RSECCNT		RTC_REG(1)	/* RTC sec */
+#define RMINCNT		RTC_REG(2)	/* RTC min */
+#define RHRCNT		RTC_REG(3)	/* RTC hour */
+#define RWKCNT		RTC_REG(4)	/* RTC week */
+#define RDAYCNT		RTC_REG(5)	/* RTC day */
+#define RMONCNT		RTC_REG(6)	/* RTC month */
+#define RYRCNT		RTC_REG(7)	/* RTC year */
+#define RSECAR		RTC_REG(8)	/* ALARM sec */
+#define RMINAR		RTC_REG(9)	/* ALARM min */
+#define RHRAR		RTC_REG(10)	/* ALARM hour */
+#define RWKAR		RTC_REG(11)	/* ALARM week */
+#define RDAYAR		RTC_REG(12)	/* ALARM day */
+#define RMONAR		RTC_REG(13)	/* ALARM month */
+#define RCR1		RTC_REG(14)	/* Control */
+#define RCR2		RTC_REG(15)	/* Control */
+
+/* ALARM Bits - or with BCD encoded value */
+#define AR_ENB		0x80	/* Enable for alarm cmp   */
 
 /* RCR1 Bits */
 #define RCR1_CF		0x80	/* Carry Flag             */
@@ -71,22 +79,28 @@
 	unsigned int alarm_irq, periodic_irq, carry_irq;
 	struct rtc_device *rtc_dev;
 	spinlock_t lock;
+	int rearm_aie;
 };
 
-static irqreturn_t sh_rtc_interrupt(int irq, void *id)
+static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
 {
-	struct platform_device *pdev = id;
+	struct platform_device *pdev = to_platform_device(dev_id);
 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
 	unsigned int tmp, events = 0;
 
 	spin_lock(&rtc->lock);
 
 	tmp = readb(rtc->regbase + RCR1);
+	tmp &= ~RCR1_CF;
 
-	if (tmp & RCR1_AF)
-		events |= RTC_AF | RTC_IRQF;
-
-	tmp &= ~(RCR1_CF | RCR1_AF);
+	if (rtc->rearm_aie) {
+		if (tmp & RCR1_AF)
+			tmp &= ~RCR1_AF;	/* try to clear AF again */
+		else {
+			tmp |= RCR1_AIE;	/* AF has cleared, rearm IRQ */
+			rtc->rearm_aie = 0;
+		}
+	}
 
 	writeb(tmp, rtc->regbase + RCR1);
 
@@ -97,9 +111,45 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sh_rtc_periodic(int irq, void *id)
+static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
 {
-	struct sh_rtc *rtc = dev_get_drvdata(id);
+	struct platform_device *pdev = to_platform_device(dev_id);
+	struct sh_rtc *rtc = platform_get_drvdata(pdev);
+	unsigned int tmp, events = 0;
+
+	spin_lock(&rtc->lock);
+
+	tmp = readb(rtc->regbase + RCR1);
+
+	/*
+	 * If AF is set then the alarm has triggered. If we clear AF while
+	 * the alarm time still matches the RTC time then AF will
+	 * immediately be set again, and if AIE is enabled then the alarm
+	 * interrupt will immediately be retrigger. So we clear AIE here
+	 * and use rtc->rearm_aie so that the carry interrupt will keep
+	 * trying to clear AF and once it stays cleared it'll re-enable
+	 * AIE.
+	 */
+	if (tmp & RCR1_AF) {
+		events |= RTC_AF | RTC_IRQF;
+
+		tmp &= ~(RCR1_AF|RCR1_AIE);
+
+		writeb(tmp, rtc->regbase + RCR1);
+
+		rtc->rearm_aie = 1;
+
+		rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
+	}
+
+	spin_unlock(&rtc->lock);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
+{
+	struct platform_device *pdev = to_platform_device(dev_id);
+	struct sh_rtc *rtc = platform_get_drvdata(pdev);
 
 	spin_lock(&rtc->lock);
 
@@ -139,10 +189,11 @@
 
 	tmp = readb(rtc->regbase + RCR1);
 
-	if (enable)
-		tmp |= RCR1_AIE;
-	else
+	if (!enable) {
 		tmp &= ~RCR1_AIE;
+		rtc->rearm_aie = 0;
+	} else if (rtc->rearm_aie == 0)
+		tmp |= RCR1_AIE;
 
 	writeb(tmp, rtc->regbase + RCR1);
 
@@ -177,7 +228,7 @@
 		goto err_bad_carry;
 	}
 
-	ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED,
+	ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
 			  "sh-rtc alarm", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
@@ -200,6 +251,7 @@
 	struct sh_rtc *rtc = dev_get_drvdata(dev);
 
 	sh_rtc_setpie(dev, 0);
+	sh_rtc_setaie(dev, 0);
 
 	free_irq(rtc->periodic_irq, dev);
 	free_irq(rtc->carry_irq, dev);
@@ -267,7 +319,7 @@
 		tm->tm_hour	= BCD2BIN(readb(rtc->regbase + RHRCNT));
 		tm->tm_wday	= BCD2BIN(readb(rtc->regbase + RWKCNT));
 		tm->tm_mday	= BCD2BIN(readb(rtc->regbase + RDAYCNT));
-		tm->tm_mon	= BCD2BIN(readb(rtc->regbase + RMONCNT));
+		tm->tm_mon	= BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1;
 
 #if defined(CONFIG_CPU_SH4)
 		yr  = readw(rtc->regbase + RYRCNT);
@@ -295,7 +347,7 @@
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
 		__FUNCTION__,
 		tm->tm_sec, tm->tm_min, tm->tm_hour,
-		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+		tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
 
 	if (rtc_valid_tm(tm) < 0)
 		dev_err(dev, "invalid date\n");
@@ -322,7 +374,7 @@
 	writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
 	writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
 	writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
-	writeb(BIN2BCD(tm->tm_mon),  rtc->regbase + RMONCNT);
+	writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT);
 
 #ifdef CONFIG_CPU_SH3
 	year = tm->tm_year % 100;
@@ -344,12 +396,136 @@
 	return 0;
 }
 
+static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off)
+{
+	unsigned int byte;
+	int value = 0xff;	/* return 0xff for ignored values */
+
+	byte = readb(rtc->regbase + reg_off);
+	if (byte & AR_ENB) {
+		byte &= ~AR_ENB;	/* strip the enable bit */
+		value = BCD2BIN(byte);
+	}
+
+	return value;
+}
+
+static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_rtc *rtc = platform_get_drvdata(pdev);
+	struct rtc_time* tm = &wkalrm->time;
+
+	spin_lock_irq(&rtc->lock);
+
+	tm->tm_sec	= sh_rtc_read_alarm_value(rtc, RSECAR);
+	tm->tm_min	= sh_rtc_read_alarm_value(rtc, RMINAR);
+	tm->tm_hour	= sh_rtc_read_alarm_value(rtc, RHRAR);
+	tm->tm_wday	= sh_rtc_read_alarm_value(rtc, RWKAR);
+	tm->tm_mday	= sh_rtc_read_alarm_value(rtc, RDAYAR);
+	tm->tm_mon	= sh_rtc_read_alarm_value(rtc, RMONAR);
+	if (tm->tm_mon > 0)
+		tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
+	tm->tm_year     = 0xffff;
+
+	spin_unlock_irq(&rtc->lock);
+
+	return 0;
+}
+
+static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
+					    int value, int reg_off)
+{
+	/* < 0 for a value that is ignored */
+	if (value < 0)
+		writeb(0, rtc->regbase + reg_off);
+	else
+		writeb(BIN2BCD(value) | AR_ENB,  rtc->regbase + reg_off);
+}
+
+static int sh_rtc_check_alarm(struct rtc_time* tm)
+{
+	/*
+	 * The original rtc says anything > 0xc0 is "don't care" or "match
+	 * all" - most users use 0xff but rtc-dev uses -1 for the same thing.
+	 * The original rtc doesn't support years - some things use -1 and
+	 * some 0xffff. We use -1 to make out tests easier.
+	 */
+	if (tm->tm_year == 0xffff)
+		tm->tm_year = -1;
+	if (tm->tm_mon >= 0xff)
+		tm->tm_mon = -1;
+	if (tm->tm_mday >= 0xff)
+		tm->tm_mday = -1;
+	if (tm->tm_wday >= 0xff)
+		tm->tm_wday = -1;
+	if (tm->tm_hour >= 0xff)
+		tm->tm_hour = -1;
+	if (tm->tm_min >= 0xff)
+		tm->tm_min = -1;
+	if (tm->tm_sec >= 0xff)
+		tm->tm_sec = -1;
+
+	if (tm->tm_year > 9999 ||
+		tm->tm_mon >= 12 ||
+		tm->tm_mday == 0 || tm->tm_mday >= 32 ||
+		tm->tm_wday >= 7 ||
+		tm->tm_hour >= 24 ||
+		tm->tm_min >= 60 ||
+		tm->tm_sec >= 60)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_rtc *rtc = platform_get_drvdata(pdev);
+	unsigned int rcr1;
+	struct rtc_time *tm = &wkalrm->time;
+	int mon, err;
+
+	err = sh_rtc_check_alarm(tm);
+	if (unlikely(err < 0))
+		return err;
+
+	spin_lock_irq(&rtc->lock);
+
+	/* disable alarm interrupt and clear flag */
+	rcr1 = readb(rtc->regbase + RCR1);
+	rcr1 &= ~RCR1_AF;
+	writeb(rcr1 & ~RCR1_AIE, rtc->regbase + RCR1);
+
+	rtc->rearm_aie = 0;
+
+	/* set alarm time */
+	sh_rtc_write_alarm_value(rtc, tm->tm_sec,  RSECAR);
+	sh_rtc_write_alarm_value(rtc, tm->tm_min,  RMINAR);
+	sh_rtc_write_alarm_value(rtc, tm->tm_hour, RHRAR);
+	sh_rtc_write_alarm_value(rtc, tm->tm_wday, RWKAR);
+	sh_rtc_write_alarm_value(rtc, tm->tm_mday, RDAYAR);
+	mon = tm->tm_mon;
+	if (mon >= 0)
+		mon += 1;
+	sh_rtc_write_alarm_value(rtc, mon, RMONAR);
+
+	/* Restore interrupt activation status */
+	writeb(rcr1, rtc->regbase + RCR1);
+
+	spin_unlock_irq(&rtc->lock);
+
+	return 0;
+}
+
 static struct rtc_class_ops sh_rtc_ops = {
 	.open		= sh_rtc_open,
 	.release	= sh_rtc_release,
 	.ioctl		= sh_rtc_ioctl,
 	.read_time	= sh_rtc_read_time,
 	.set_time	= sh_rtc_set_time,
+	.read_alarm	= sh_rtc_read_alarm,
+	.set_alarm	= sh_rtc_set_alarm,
 	.proc		= sh_rtc_proc,
 };
 
@@ -442,7 +618,7 @@
 }
 static struct platform_driver sh_rtc_platform_driver = {
 	.driver		= {
-		.name	= "sh-rtc",
+		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sh_rtc_probe,
@@ -463,5 +639,6 @@
 module_exit(sh_rtc_exit);
 
 MODULE_DESCRIPTION("SuperH on-chip RTC driver");
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, Jamie Lenehan <lenehan@twibble.org>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 9031b57..c53b696 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -319,6 +319,28 @@
 
 	sci_out(port, SCFCR, fcr_val);
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+{
+	unsigned int fcr_val = 0;
+
+	if (cflag & CRTSCTS) {
+		fcr_val |= SCFCR_MCE;
+
+		ctrl_outw(0x0000, PORT_PSCR);
+	} else {
+		unsigned short data;
+
+		data = ctrl_inw(PORT_PSCR);
+		data &= 0x033f;
+		data |= 0x0400;
+		ctrl_outw(data, PORT_PSCR);
+
+		ctrl_outw(ctrl_inw(SCSPTR0) & 0x17, SCSPTR0);
+	}
+
+	sci_out(port, SCFCR, fcr_val);
+}
 #else
 /* For SH7750 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index e4557cc..77f7d63 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -90,6 +90,13 @@
 # define SCSPTR3 0xffe30010	/* 16 bit SCIF */
 # define SCSCR_INIT(port) 0x32	/* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+# define SCPDR0			0xA405013E	/* 16 bit SCIF0 PSDR */
+# define SCSPTR0		SCPDR0
+# define SCIF_ORER		0x0001	/* overrun error bit */
+# define SCSCR_INIT(port)	0x0038	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
+# define PORT_PSCR		0xA405011E
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -495,6 +502,7 @@
 		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
 	if (port->mapbase == 0xfe620000)
 		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+	return 1;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7300)
 static inline int sci_rxd_in(struct uart_port *port)
@@ -521,6 +529,13 @@
 		return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
 	return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+	if (port->mapbase == 0xffe00000)
+		return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
+	return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 static inline int sci_rxd_in(struct uart_port *port)
 {
@@ -550,6 +565,7 @@
 		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
 	if (port->mapbase == 0xff925000)
 		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+	return 1;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 static inline int sci_rxd_in(struct uart_port *port)
@@ -558,6 +574,7 @@
 		return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
 	if (port->mapbase == 0xffe10000)
 		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+	return 1;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7206)
 static inline int sci_rxd_in(struct uart_port *port)
@@ -570,6 +587,7 @@
 		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
 	if (port->mapbase == 0xfffe9800)
 		return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+	return 1;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
 static inline int sci_rxd_in(struct uart_port *port)
@@ -580,6 +598,7 @@
 		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
 	if (port->mapbase == 0xf8420000)
 		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+	return 1;
 }
 #endif
 
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 869725a..e7c5b21 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -120,19 +120,19 @@
 void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
 {
 	if (rinfo->i2c[0].rinfo)
-		i2c_bit_del_bus(&rinfo->i2c[0].adapter);
+		i2c_del_adapter(&rinfo->i2c[0].adapter);
 	rinfo->i2c[0].rinfo = NULL;
 
 	if (rinfo->i2c[1].rinfo)
-		i2c_bit_del_bus(&rinfo->i2c[1].adapter);
+		i2c_del_adapter(&rinfo->i2c[1].adapter);
 	rinfo->i2c[1].rinfo = NULL;
 
 	if (rinfo->i2c[2].rinfo)
-		i2c_bit_del_bus(&rinfo->i2c[2].adapter);
+		i2c_del_adapter(&rinfo->i2c[2].adapter);
 	rinfo->i2c[2].rinfo = NULL;
 
 	if (rinfo->i2c[3].rinfo)
-		i2c_bit_del_bus(&rinfo->i2c[3].adapter);
+		i2c_del_adapter(&rinfo->i2c[3].adapter);
 	rinfo->i2c[3].rinfo = NULL;
 }
 
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index b952e45..961f4d4 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -137,15 +137,15 @@
 void i810_delete_i2c_busses(struct i810fb_par *par)
 {
         if (par->chan[0].par)
-                i2c_bit_del_bus(&par->chan[0].adapter);
+		i2c_del_adapter(&par->chan[0].adapter);
         par->chan[0].par = NULL;
 
 	if (par->chan[1].par)
-		i2c_bit_del_bus(&par->chan[1].adapter);
+		i2c_del_adapter(&par->chan[1].adapter);
 	par->chan[1].par = NULL;
 
 	if (par->chan[2].par)
-		i2c_bit_del_bus(&par->chan[2].adapter);
+		i2c_del_adapter(&par->chan[2].adapter);
 	par->chan[2].par = NULL;
 }
 
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index 5686e21..33bc41f 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -188,11 +188,11 @@
 
 	for (i = 0; i < MAX_OUTPUTS; i++) {
 		if (dinfo->output[i].i2c_bus.dinfo) {
-			i2c_bit_del_bus(&dinfo->output[i].i2c_bus.adapter);
+			i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
 			dinfo->output[i].i2c_bus.dinfo = NULL;
 		}
 		if (dinfo->output[i].ddc_bus.dinfo) {
-			i2c_bit_del_bus(&dinfo->output[i].ddc_bus.adapter);
+			i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
 			dinfo->output[i].ddc_bus.dinfo = NULL;
 		}
 	}
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 795c1a9..797b423 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -124,7 +124,7 @@
 
 static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
 	if (b->initialized) {
-		i2c_bit_del_bus(&b->adapter);
+		i2c_del_adapter(&b->adapter);
 		b->initialized = 0;
 	}
 }
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 442e853..8454adf 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -147,15 +147,15 @@
 void nvidia_delete_i2c_busses(struct nvidia_par *par)
 {
 	if (par->chan[0].par)
-		i2c_bit_del_bus(&par->chan[0].adapter);
+		i2c_del_adapter(&par->chan[0].adapter);
 	par->chan[0].par = NULL;
 
 	if (par->chan[1].par)
-		i2c_bit_del_bus(&par->chan[1].adapter);
+		i2c_del_adapter(&par->chan[1].adapter);
 	par->chan[1].par = NULL;
 
 	if (par->chan[2].par)
-		i2c_bit_del_bus(&par->chan[2].adapter);
+		i2c_del_adapter(&par->chan[2].adapter);
 	par->chan[2].par = NULL;
 
 }
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index c15b259..01b85e3 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -144,15 +144,15 @@
 void riva_delete_i2c_busses(struct riva_par *par)
 {
 	if (par->chan[0].par)
-		i2c_bit_del_bus(&par->chan[0].adapter);
+		i2c_del_adapter(&par->chan[0].adapter);
 	par->chan[0].par = NULL;
 
 	if (par->chan[1].par)
-		i2c_bit_del_bus(&par->chan[1].adapter);
+		i2c_del_adapter(&par->chan[1].adapter);
 	par->chan[1].par = NULL;
 
 	if (par->chan[2].par)
-		i2c_bit_del_bus(&par->chan[2].adapter);
+		i2c_del_adapter(&par->chan[2].adapter);
 	par->chan[2].par = NULL;
 }
 
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index cef5bf5..1411f3b 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -208,7 +208,7 @@
 	struct savagefb_par *par = info->par;
 
 	if (par->chan.par)
-		i2c_bit_del_bus(&par->chan.adapter);
+		i2c_del_adapter(&par->chan.adapter);
 
 	par->chan.par = NULL;
 }
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index eb550b3..38f70ac 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -29,31 +29,21 @@
 /*
  *	 file system option (superblock flag)
  */
-/* mount time flag to disable journaling to disk */
-#define JFS_NOINTEGRITY 0x00000010
+
+/* directory option */
+#define JFS_UNICODE	0x00000001	/* unicode name */
 
 /* mount time flags for error handling */
 #define JFS_ERR_REMOUNT_RO 0x00000002   /* remount read-only */
 #define JFS_ERR_CONTINUE   0x00000004   /* continue */
 #define JFS_ERR_PANIC      0x00000008   /* panic */
 
+/* Quota support */
 #define	JFS_USRQUOTA	0x00000010
 #define	JFS_GRPQUOTA	0x00000020
 
-/* platform option (conditional compilation) */
-#define JFS_AIX		0x80000000	/* AIX support */
-/*	POSIX name/directory  support */
-
-#define JFS_OS2		0x40000000	/* OS/2 support */
-/*	case-insensitive name/directory support */
-
-#define JFS_DFS		0x20000000	/* DCE DFS LFS support */
-
-#define JFS_LINUX	0x10000000	/* Linux support */
-/*	case-sensitive name/directory support */
-
-/* directory option */
-#define JFS_UNICODE	0x00000001	/* unicode name */
+/* mount time flag to disable journaling to disk */
+#define JFS_NOINTEGRITY 0x00000040
 
 /* commit option */
 #define	JFS_COMMIT	0x00000f00	/* commit option mask */
@@ -61,6 +51,7 @@
 #define	JFS_LAZYCOMMIT	0x00000200	/* lazy commit */
 #define	JFS_TMPFS	0x00000400	/* temporary file system -
 					 * do not log/commit:
+					 * Never implemented
 					 */
 
 /* log logical volume option */
@@ -74,16 +65,25 @@
 #define JFS_SPARSE	0x00020000	/* sparse regular file */
 
 /* DASD Limits		F226941 */
-#define JFS_DASD_ENABLED	0x00040000	/* DASD limits enabled */
-#define	JFS_DASD_PRIME		0x00080000	/* Prime DASD usage on boot */
+#define JFS_DASD_ENABLED 0x00040000	/* DASD limits enabled */
+#define	JFS_DASD_PRIME	0x00080000	/* Prime DASD usage on boot */
 
 /* big endian flag */
-#define	JFS_SWAP_BYTES		0x00100000	/* running on big endian computer */
+#define	JFS_SWAP_BYTES	0x00100000	/* running on big endian computer */
 
 /* Directory index */
-#define JFS_DIR_INDEX		0x00200000	/* Persistent index for */
-						/* directory entries    */
+#define JFS_DIR_INDEX	0x00200000	/* Persistent index for */
 
+/* platform options */
+#define JFS_LINUX	0x10000000	/* Linux support */
+#define JFS_DFS		0x20000000	/* DCE DFS LFS support */
+/*	Never implemented */
+
+#define JFS_OS2		0x40000000	/* OS/2 support */
+/*	case-insensitive name/directory support */
+
+#define JFS_AIX		0x80000000	/* AIX support */
+/*	POSIX name/directory  support - Never implemented*/
 
 /*
  *	buffer cache configuration
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index d11753c..357f1d5 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -35,7 +35,7 @@
 /* for now we operate under the assertion that there can be only one
  * cluster active at a time.  Changing this will require trickling
  * cluster references throughout where nodes are looked up */
-static struct o2nm_cluster *o2nm_single_cluster = NULL;
+struct o2nm_cluster *o2nm_single_cluster = NULL;
 
 #define OCFS2_MAX_HB_CTL_PATH 256
 static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";
@@ -97,17 +97,6 @@
 }
 EXPORT_SYMBOL_GPL(o2nm_get_hb_ctl_path);
 
-struct o2nm_cluster {
-	struct config_group	cl_group;
-	unsigned		cl_has_local:1;
-	u8			cl_local_node;
-	rwlock_t		cl_nodes_lock;
-	struct o2nm_node  	*cl_nodes[O2NM_MAX_NODES];
-	struct rb_root		cl_node_ip_tree;
-	/* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */
-	unsigned long	cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
-};
-
 struct o2nm_node *o2nm_get_node_by_num(u8 node_num)
 {
 	struct o2nm_node *node = NULL;
@@ -543,6 +532,179 @@
 }
 #endif
 
+struct o2nm_cluster_attribute {
+	struct configfs_attribute attr;
+	ssize_t (*show)(struct o2nm_cluster *, char *);
+	ssize_t (*store)(struct o2nm_cluster *, const char *, size_t);
+};
+
+static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
+                                       unsigned int *val)
+{
+	unsigned long tmp;
+	char *p = (char *)page;
+
+	tmp = simple_strtoul(p, &p, 0);
+	if (!p || (*p && (*p != '\n')))
+		return -EINVAL;
+
+	if (tmp == 0)
+		return -EINVAL;
+	if (tmp >= (u32)-1)
+		return -ERANGE;
+
+	*val = tmp;
+
+	return count;
+}
+
+static ssize_t o2nm_cluster_attr_idle_timeout_ms_read(
+	struct o2nm_cluster *cluster, char *page)
+{
+	return sprintf(page, "%u\n", cluster->cl_idle_timeout_ms);
+}
+
+static ssize_t o2nm_cluster_attr_idle_timeout_ms_write(
+	struct o2nm_cluster *cluster, const char *page, size_t count)
+{
+	ssize_t ret;
+	unsigned int val;
+
+	ret =  o2nm_cluster_attr_write(page, count, &val);
+
+	if (ret > 0) {
+		if (cluster->cl_idle_timeout_ms != val
+			&& o2net_num_connected_peers()) {
+			mlog(ML_NOTICE,
+			     "o2net: cannot change idle timeout after "
+			     "the first peer has agreed to it."
+			     "  %d connected peers\n",
+			     o2net_num_connected_peers());
+			ret = -EINVAL;
+		} else if (val <= cluster->cl_keepalive_delay_ms) {
+			mlog(ML_NOTICE, "o2net: idle timeout must be larger "
+			     "than keepalive delay\n");
+			ret = -EINVAL;
+		} else {
+			cluster->cl_idle_timeout_ms = val;
+		}
+	}
+
+	return ret;
+}
+
+static ssize_t o2nm_cluster_attr_keepalive_delay_ms_read(
+	struct o2nm_cluster *cluster, char *page)
+{
+	return sprintf(page, "%u\n", cluster->cl_keepalive_delay_ms);
+}
+
+static ssize_t o2nm_cluster_attr_keepalive_delay_ms_write(
+	struct o2nm_cluster *cluster, const char *page, size_t count)
+{
+	ssize_t ret;
+	unsigned int val;
+
+	ret =  o2nm_cluster_attr_write(page, count, &val);
+
+	if (ret > 0) {
+		if (cluster->cl_keepalive_delay_ms != val
+		    && o2net_num_connected_peers()) {
+			mlog(ML_NOTICE,
+			     "o2net: cannot change keepalive delay after"
+			     " the first peer has agreed to it."
+			     "  %d connected peers\n",
+			     o2net_num_connected_peers());
+			ret = -EINVAL;
+		} else if (val >= cluster->cl_idle_timeout_ms) {
+			mlog(ML_NOTICE, "o2net: keepalive delay must be "
+			     "smaller than idle timeout\n");
+			ret = -EINVAL;
+		} else {
+			cluster->cl_keepalive_delay_ms = val;
+		}
+	}
+
+	return ret;
+}
+
+static ssize_t o2nm_cluster_attr_reconnect_delay_ms_read(
+	struct o2nm_cluster *cluster, char *page)
+{
+	return sprintf(page, "%u\n", cluster->cl_reconnect_delay_ms);
+}
+
+static ssize_t o2nm_cluster_attr_reconnect_delay_ms_write(
+	struct o2nm_cluster *cluster, const char *page, size_t count)
+{
+	return o2nm_cluster_attr_write(page, count,
+	                               &cluster->cl_reconnect_delay_ms);
+}
+static struct o2nm_cluster_attribute o2nm_cluster_attr_idle_timeout_ms = {
+	.attr	= { .ca_owner = THIS_MODULE,
+		    .ca_name = "idle_timeout_ms",
+		    .ca_mode = S_IRUGO | S_IWUSR },
+	.show	= o2nm_cluster_attr_idle_timeout_ms_read,
+	.store	= o2nm_cluster_attr_idle_timeout_ms_write,
+};
+
+static struct o2nm_cluster_attribute o2nm_cluster_attr_keepalive_delay_ms = {
+	.attr	= { .ca_owner = THIS_MODULE,
+		    .ca_name = "keepalive_delay_ms",
+		    .ca_mode = S_IRUGO | S_IWUSR },
+	.show	= o2nm_cluster_attr_keepalive_delay_ms_read,
+	.store	= o2nm_cluster_attr_keepalive_delay_ms_write,
+};
+
+static struct o2nm_cluster_attribute o2nm_cluster_attr_reconnect_delay_ms = {
+	.attr	= { .ca_owner = THIS_MODULE,
+		    .ca_name = "reconnect_delay_ms",
+		    .ca_mode = S_IRUGO | S_IWUSR },
+	.show	= o2nm_cluster_attr_reconnect_delay_ms_read,
+	.store	= o2nm_cluster_attr_reconnect_delay_ms_write,
+};
+
+static struct configfs_attribute *o2nm_cluster_attrs[] = {
+	&o2nm_cluster_attr_idle_timeout_ms.attr,
+	&o2nm_cluster_attr_keepalive_delay_ms.attr,
+	&o2nm_cluster_attr_reconnect_delay_ms.attr,
+	NULL,
+};
+static ssize_t o2nm_cluster_show(struct config_item *item,
+                                 struct configfs_attribute *attr,
+                                 char *page)
+{
+	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
+	struct o2nm_cluster_attribute *o2nm_cluster_attr =
+		container_of(attr, struct o2nm_cluster_attribute, attr);
+	ssize_t ret = 0;
+
+	if (o2nm_cluster_attr->show)
+		ret = o2nm_cluster_attr->show(cluster, page);
+	return ret;
+}
+
+static ssize_t o2nm_cluster_store(struct config_item *item,
+                                  struct configfs_attribute *attr,
+                                  const char *page, size_t count)
+{
+	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
+	struct o2nm_cluster_attribute *o2nm_cluster_attr =
+		container_of(attr, struct o2nm_cluster_attribute, attr);
+	ssize_t ret;
+
+	if (o2nm_cluster_attr->store == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = o2nm_cluster_attr->store(cluster, page, count);
+	if (ret < count)
+		goto out;
+out:
+	return ret;
+}
+
 static struct config_item *o2nm_node_group_make_item(struct config_group *group,
 						     const char *name)
 {
@@ -624,10 +786,13 @@
 
 static struct configfs_item_operations o2nm_cluster_item_ops = {
 	.release	= o2nm_cluster_release,
+	.show_attribute		= o2nm_cluster_show,
+	.store_attribute	= o2nm_cluster_store,
 };
 
 static struct config_item_type o2nm_cluster_type = {
 	.ct_item_ops	= &o2nm_cluster_item_ops,
+	.ct_attrs	= o2nm_cluster_attrs,
 	.ct_owner	= THIS_MODULE,
 };
 
@@ -678,6 +843,9 @@
 	cluster->cl_group.default_groups[2] = NULL;
 	rwlock_init(&cluster->cl_nodes_lock);
 	cluster->cl_node_ip_tree = RB_ROOT;
+	cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT;
+	cluster->cl_idle_timeout_ms    = O2NET_IDLE_TIMEOUT_MS_DEFAULT;
+	cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT;
 
 	ret = &cluster->cl_group;
 	o2nm_single_cluster = cluster;
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
index fce8033..8fb23ca 100644
--- a/fs/ocfs2/cluster/nodemanager.h
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -53,6 +53,23 @@
 	unsigned long		nd_set_attributes;
 };
 
+struct o2nm_cluster {
+	struct config_group	cl_group;
+	unsigned		cl_has_local:1;
+	u8			cl_local_node;
+	rwlock_t		cl_nodes_lock;
+	struct o2nm_node  	*cl_nodes[O2NM_MAX_NODES];
+	struct rb_root		cl_node_ip_tree;
+	unsigned int		cl_idle_timeout_ms;
+	unsigned int		cl_keepalive_delay_ms;
+	unsigned int		cl_reconnect_delay_ms;
+
+	/* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */
+	unsigned long	cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+};
+
+extern struct o2nm_cluster *o2nm_single_cluster;
+
 u8 o2nm_this_node(void);
 
 int o2nm_configured_node_map(unsigned long *map, unsigned bytes);
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 9b3209d..457753d 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -147,6 +147,28 @@
 static void o2net_sc_send_keep_req(struct work_struct *work);
 static void o2net_idle_timer(unsigned long data);
 static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
+static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc);
+
+/*
+ * FIXME: These should use to_o2nm_cluster_from_node(), but we end up
+ * losing our parent link to the cluster during shutdown. This can be
+ * solved by adding a pre-removal callback to configfs, or passing
+ * around the cluster with the node. -jeffm
+ */
+static inline int o2net_reconnect_delay(struct o2nm_node *node)
+{
+	return o2nm_single_cluster->cl_reconnect_delay_ms;
+}
+
+static inline int o2net_keepalive_delay(struct o2nm_node *node)
+{
+	return o2nm_single_cluster->cl_keepalive_delay_ms;
+}
+
+static inline int o2net_idle_timeout(struct o2nm_node *node)
+{
+	return o2nm_single_cluster->cl_idle_timeout_ms;
+}
 
 static inline int o2net_sys_err_to_errno(enum o2net_system_error err)
 {
@@ -271,6 +293,8 @@
 {
 	struct o2net_sock_container *sc = container_of(kref,
 					struct o2net_sock_container, sc_kref);
+	BUG_ON(timer_pending(&sc->sc_idle_timeout));
+
 	sclog(sc, "releasing\n");
 
 	if (sc->sc_sock) {
@@ -356,6 +380,13 @@
 		sc_put(sc);
 }
 
+static atomic_t o2net_connected_peers = ATOMIC_INIT(0);
+
+int o2net_num_connected_peers(void)
+{
+	return atomic_read(&o2net_connected_peers);
+}
+
 static void o2net_set_nn_state(struct o2net_node *nn,
 			       struct o2net_sock_container *sc,
 			       unsigned valid, int err)
@@ -366,6 +397,11 @@
 
 	assert_spin_locked(&nn->nn_lock);
 
+	if (old_sc && !sc)
+		atomic_dec(&o2net_connected_peers);
+	else if (!old_sc && sc)
+		atomic_inc(&o2net_connected_peers);
+
 	/* the node num comparison and single connect/accept path should stop
 	 * an non-null sc from being overwritten with another */
 	BUG_ON(sc && nn->nn_sc && nn->nn_sc != sc);
@@ -424,9 +460,9 @@
 		/* delay if we're withing a RECONNECT_DELAY of the
 		 * last attempt */
 		delay = (nn->nn_last_connect_attempt +
-			 msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS))
+			 msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
 			- jiffies;
-		if (delay > msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS))
+		if (delay > msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
 			delay = 0;
 		mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
 		queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
@@ -1099,13 +1135,51 @@
 		return -1;
 	}
 
+	/*
+	 * Ensure timeouts are consistent with other nodes, otherwise
+	 * we can end up with one node thinking that the other must be down,
+	 * but isn't. This can ultimately cause corruption.
+	 */
+	if (be32_to_cpu(hand->o2net_idle_timeout_ms) !=
+				o2net_idle_timeout(sc->sc_node)) {
+		mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of "
+		     "%u ms, but we use %u ms locally.  disconnecting\n",
+		     SC_NODEF_ARGS(sc),
+		     be32_to_cpu(hand->o2net_idle_timeout_ms),
+		     o2net_idle_timeout(sc->sc_node));
+		o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+		return -1;
+	}
+
+	if (be32_to_cpu(hand->o2net_keepalive_delay_ms) !=
+			o2net_keepalive_delay(sc->sc_node)) {
+		mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of "
+		     "%u ms, but we use %u ms locally.  disconnecting\n",
+		     SC_NODEF_ARGS(sc),
+		     be32_to_cpu(hand->o2net_keepalive_delay_ms),
+		     o2net_keepalive_delay(sc->sc_node));
+		o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+		return -1;
+	}
+
+	if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) !=
+			O2HB_MAX_WRITE_TIMEOUT_MS) {
+		mlog(ML_NOTICE, SC_NODEF_FMT " uses a heartbeat timeout of "
+		     "%u ms, but we use %u ms locally.  disconnecting\n",
+		     SC_NODEF_ARGS(sc),
+		     be32_to_cpu(hand->o2hb_heartbeat_timeout_ms),
+		     O2HB_MAX_WRITE_TIMEOUT_MS);
+		o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+		return -1;
+	}
+
 	sc->sc_handshake_ok = 1;
 
 	spin_lock(&nn->nn_lock);
 	/* set valid and queue the idle timers only if it hasn't been
 	 * shut down already */
 	if (nn->nn_sc == sc) {
-		o2net_sc_postpone_idle(sc);
+		o2net_sc_reset_idle_timer(sc);
 		o2net_set_nn_state(nn, sc, 1, 0);
 	}
 	spin_unlock(&nn->nn_lock);
@@ -1131,6 +1205,23 @@
 	sclog(sc, "receiving\n");
 	do_gettimeofday(&sc->sc_tv_advance_start);
 
+	if (unlikely(sc->sc_handshake_ok == 0)) {
+		if(sc->sc_page_off < sizeof(struct o2net_handshake)) {
+			data = page_address(sc->sc_page) + sc->sc_page_off;
+			datalen = sizeof(struct o2net_handshake) - sc->sc_page_off;
+			ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen);
+			if (ret > 0)
+				sc->sc_page_off += ret;
+		}
+
+		if (sc->sc_page_off == sizeof(struct o2net_handshake)) {
+			o2net_check_handshake(sc);
+			if (unlikely(sc->sc_handshake_ok == 0))
+				ret = -EPROTO;
+		}
+		goto out;
+	}
+
 	/* do we need more header? */
 	if (sc->sc_page_off < sizeof(struct o2net_msg)) {
 		data = page_address(sc->sc_page) + sc->sc_page_off;
@@ -1138,15 +1229,6 @@
 		ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen);
 		if (ret > 0) {
 			sc->sc_page_off += ret;
-
-			/* this working relies on the handshake being
-			 * smaller than the normal message header */
-			if (sc->sc_page_off >= sizeof(struct o2net_handshake)&&
-			    !sc->sc_handshake_ok && o2net_check_handshake(sc)) {
-				ret = -EPROTO;
-				goto out;
-			}
-
 			/* only swab incoming here.. we can
 			 * only get here once as we cross from
 			 * being under to over */
@@ -1248,6 +1330,18 @@
 	return ret;
 }
 
+static void o2net_initialize_handshake(void)
+{
+	o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32(
+		O2HB_MAX_WRITE_TIMEOUT_MS);
+	o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(
+		o2net_idle_timeout(NULL));
+	o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32(
+		o2net_keepalive_delay(NULL));
+	o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32(
+		o2net_reconnect_delay(NULL));
+}
+
 /* ------------------------------------------------------------ */
 
 /* called when a connect completes and after a sock is accepted.  the
@@ -1262,6 +1356,7 @@
               (unsigned long long)O2NET_PROTOCOL_VERSION,
 	      (unsigned long long)be64_to_cpu(o2net_hand->connector_id));
 
+	o2net_initialize_handshake();
 	o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand));
 	sc_put(sc);
 }
@@ -1287,8 +1382,10 @@
 
 	do_gettimeofday(&now);
 
-	printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for 10 "
-	     "seconds, shutting it down.\n", SC_NODEF_ARGS(sc));
+	printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
+	     "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
+		     o2net_idle_timeout(sc->sc_node) / 1000,
+		     o2net_idle_timeout(sc->sc_node) % 1000);
 	mlog(ML_NOTICE, "here are some times that might help debug the "
 	     "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
 	     "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
@@ -1306,14 +1403,21 @@
 	o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
 }
 
-static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)
 {
 	o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
 	o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work,
-				    O2NET_KEEPALIVE_DELAY_SECS * HZ);
+		      msecs_to_jiffies(o2net_keepalive_delay(sc->sc_node)));
 	do_gettimeofday(&sc->sc_tv_timer);
 	mod_timer(&sc->sc_idle_timeout,
-		  jiffies + (O2NET_IDLE_TIMEOUT_SECS * HZ));
+	       jiffies + msecs_to_jiffies(o2net_idle_timeout(sc->sc_node)));
+}
+
+static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+{
+	/* Only push out an existing timer */
+	if (timer_pending(&sc->sc_idle_timeout))
+		o2net_sc_reset_idle_timer(sc);
 }
 
 /* this work func is kicked whenever a path sets the nn state which doesn't
@@ -1435,9 +1539,12 @@
 
 	spin_lock(&nn->nn_lock);
 	if (!nn->nn_sc_valid) {
+		struct o2nm_node *node = nn->nn_sc->sc_node;
 		mlog(ML_ERROR, "no connection established with node %u after "
-		     "%u seconds, giving up and returning errors.\n",
-		     o2net_num_from_nn(nn), O2NET_IDLE_TIMEOUT_SECS);
+		     "%u.%u seconds, giving up and returning errors.\n",
+		     o2net_num_from_nn(nn),
+		     o2net_idle_timeout(node) / 1000,
+		     o2net_idle_timeout(node) % 1000);
 
 		o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
 	}
@@ -1478,6 +1585,8 @@
 
 	if (node_num != o2nm_this_node())
 		o2net_disconnect_node(node);
+
+	BUG_ON(atomic_read(&o2net_connected_peers) < 0);
 }
 
 static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
@@ -1489,14 +1598,14 @@
 
 	/* ensure an immediate connect attempt */
 	nn->nn_last_connect_attempt = jiffies -
-		(msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS) + 1);
+		(msecs_to_jiffies(o2net_reconnect_delay(node)) + 1);
 
 	if (node_num != o2nm_this_node()) {
 		/* heartbeat doesn't work unless a local node number is
 		 * configured and doing so brings up the o2net_wq, so we can
 		 * use it.. */
 		queue_delayed_work(o2net_wq, &nn->nn_connect_expired,
-				   O2NET_IDLE_TIMEOUT_SECS * HZ);
+		                   msecs_to_jiffies(o2net_idle_timeout(node)));
 
 		/* believe it or not, accept and node hearbeating testing
 		 * can succeed for this node before we got here.. so
@@ -1641,6 +1750,7 @@
 	o2net_register_callbacks(sc->sc_sock->sk, sc);
 	o2net_sc_queue_work(sc, &sc->sc_rx_work);
 
+	o2net_initialize_handshake();
 	o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand));
 
 out:
diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h
index 616ff2b..21a4e43 100644
--- a/fs/ocfs2/cluster/tcp.h
+++ b/fs/ocfs2/cluster/tcp.h
@@ -54,6 +54,13 @@
 
 #define O2NET_MAX_PAYLOAD_BYTES  (4096 - sizeof(struct o2net_msg))
 
+/* same as hb delay, we're waiting for another node to recognize our hb */
+#define O2NET_RECONNECT_DELAY_MS_DEFAULT	2000
+
+#define O2NET_KEEPALIVE_DELAY_MS_DEFAULT	5000
+#define O2NET_IDLE_TIMEOUT_MS_DEFAULT		10000
+
+
 /* TODO: figure this out.... */
 static inline int o2net_link_down(int err, struct socket *sock)
 {
@@ -101,6 +108,7 @@
 int o2net_start_listening(struct o2nm_node *node);
 void o2net_stop_listening(struct o2nm_node *node);
 void o2net_disconnect_node(struct o2nm_node *node);
+int o2net_num_connected_peers(void);
 
 int o2net_init(void);
 void o2net_exit(void);
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h
index daebbd3..b700dc9 100644
--- a/fs/ocfs2/cluster/tcp_internal.h
+++ b/fs/ocfs2/cluster/tcp_internal.h
@@ -27,23 +27,20 @@
 #define O2NET_MSG_KEEP_REQ_MAGIC  ((u16)0xfa57)
 #define O2NET_MSG_KEEP_RESP_MAGIC ((u16)0xfa58)
 
-/* same as hb delay, we're waiting for another node to recognize our hb */
-#define O2NET_RECONNECT_DELAY_MS	O2HB_REGION_TIMEOUT_MS
-
 /* we're delaying our quorum decision so that heartbeat will have timed
  * out truly dead nodes by the time we come around to making decisions
  * on their number */
 #define O2NET_QUORUM_DELAY_MS	((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS)
 
-#define O2NET_KEEPALIVE_DELAY_SECS	5
-#define O2NET_IDLE_TIMEOUT_SECS		10
-
 /* 
  * This version number represents quite a lot, unfortunately.  It not
  * only represents the raw network message protocol on the wire but also
  * locking semantics of the file system using the protocol.  It should 
  * be somewhere else, I'm sure, but right now it isn't.
  *
+ * New in version 5:
+ * 	- Network timeout checking protocol
+ *
  * New in version 4:
  * 	- Remove i_generation from lock names for better stat performance.
  *
@@ -54,10 +51,14 @@
  * 	- full 64 bit i_size in the metadata lock lvbs
  * 	- introduction of "rw" lock and pushing meta/data locking down
  */
-#define O2NET_PROTOCOL_VERSION 4ULL
+#define O2NET_PROTOCOL_VERSION 5ULL
 struct o2net_handshake {
 	__be64	protocol_version;
 	__be64	connector_id;
+	__be32  o2hb_heartbeat_timeout_ms;
+	__be32  o2net_idle_timeout_ms;
+	__be32  o2net_keepalive_delay_ms;
+	__be32  o2net_reconnect_delay_ms;
 };
 
 struct o2net_node {
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 69fba16..e622013 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -770,7 +770,7 @@
 			     int dlm_flags)
 {
 	int ret = 0;
-	enum dlm_status status;
+	enum dlm_status status = DLM_NORMAL;
 	unsigned long flags;
 
 	mlog_entry_void();
@@ -1138,6 +1138,7 @@
 {
 	int status, level;
 	struct ocfs2_lock_res *lockres;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	BUG_ON(!inode);
 
@@ -1147,6 +1148,9 @@
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
 	     write ? "EXMODE" : "PRMODE");
 
+	if (ocfs2_mount_local(osb))
+		return 0;
+
 	lockres = &OCFS2_I(inode)->ip_rw_lockres;
 
 	level = write ? LKM_EXMODE : LKM_PRMODE;
@@ -1164,6 +1168,7 @@
 {
 	int level = write ? LKM_EXMODE : LKM_PRMODE;
 	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	mlog_entry_void();
 
@@ -1171,7 +1176,8 @@
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
 	     write ? "EXMODE" : "PRMODE");
 
-	ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
+	if (!ocfs2_mount_local(osb))
+		ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
 
 	mlog_exit_void();
 }
@@ -1182,6 +1188,7 @@
 {
 	int status = 0, level;
 	struct ocfs2_lock_res *lockres;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	BUG_ON(!inode);
 
@@ -1201,6 +1208,9 @@
 		goto out;
 	}
 
+	if (ocfs2_mount_local(osb))
+		goto out;
+
 	lockres = &OCFS2_I(inode)->ip_data_lockres;
 
 	level = write ? LKM_EXMODE : LKM_PRMODE;
@@ -1269,6 +1279,7 @@
 {
 	int level = write ? LKM_EXMODE : LKM_PRMODE;
 	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	mlog_entry_void();
 
@@ -1276,7 +1287,8 @@
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
 	     write ? "EXMODE" : "PRMODE");
 
-	if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+	if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
+	    !ocfs2_mount_local(osb))
 		ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
 
 	mlog_exit_void();
@@ -1467,8 +1479,9 @@
 {
 	int status = 0;
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
-	struct ocfs2_lock_res *lockres;
+	struct ocfs2_lock_res *lockres = NULL;
 	struct ocfs2_dinode *fe;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	mlog_entry_void();
 
@@ -1483,10 +1496,12 @@
 	}
 	spin_unlock(&oi->ip_lock);
 
-	lockres = &oi->ip_meta_lockres;
+	if (!ocfs2_mount_local(osb)) {
+		lockres = &oi->ip_meta_lockres;
 
-	if (!ocfs2_should_refresh_lock_res(lockres))
-		goto bail;
+		if (!ocfs2_should_refresh_lock_res(lockres))
+			goto bail;
+	}
 
 	/* This will discard any caching information we might have had
 	 * for the inode metadata. */
@@ -1496,7 +1511,7 @@
 	 * map (directories, bitmap files, etc) */
 	ocfs2_extent_map_trunc(inode, 0);
 
-	if (ocfs2_meta_lvb_is_trustable(inode, lockres)) {
+	if (lockres && ocfs2_meta_lvb_is_trustable(inode, lockres)) {
 		mlog(0, "Trusting LVB on inode %llu\n",
 		     (unsigned long long)oi->ip_blkno);
 		ocfs2_refresh_inode_from_lvb(inode);
@@ -1543,7 +1558,8 @@
 
 	status = 0;
 bail_refresh:
-	ocfs2_complete_lock_res_refresh(lockres, status);
+	if (lockres)
+		ocfs2_complete_lock_res_refresh(lockres, status);
 bail:
 	mlog_exit(status);
 	return status;
@@ -1585,7 +1601,7 @@
 			 int arg_flags)
 {
 	int status, level, dlm_flags, acquired;
-	struct ocfs2_lock_res *lockres;
+	struct ocfs2_lock_res *lockres = NULL;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct buffer_head *local_bh = NULL;
 
@@ -1607,6 +1623,9 @@
 		goto bail;
 	}
 
+	if (ocfs2_mount_local(osb))
+		goto local;
+
 	if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
 		wait_event(osb->recovery_event,
 			   ocfs2_node_map_is_empty(osb, &osb->recovery_map));
@@ -1636,6 +1655,7 @@
 		wait_event(osb->recovery_event,
 			   ocfs2_node_map_is_empty(osb, &osb->recovery_map));
 
+local:
 	/*
 	 * We only see this flag if we're being called from
 	 * ocfs2_read_locked_inode(). It means we're locking an inode
@@ -1644,7 +1664,8 @@
 	 */
 	if (inode->i_state & I_NEW) {
 		status = 0;
-		ocfs2_complete_lock_res_refresh(lockres, 0);
+		if (lockres)
+			ocfs2_complete_lock_res_refresh(lockres, 0);
 		goto bail;
 	}
 
@@ -1767,6 +1788,7 @@
 {
 	int level = ex ? LKM_EXMODE : LKM_PRMODE;
 	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	mlog_entry_void();
 
@@ -1774,7 +1796,8 @@
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
 	     ex ? "EXMODE" : "PRMODE");
 
-	if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+	if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
+	    !ocfs2_mount_local(osb))
 		ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
 
 	mlog_exit_void();
@@ -1783,7 +1806,7 @@
 int ocfs2_super_lock(struct ocfs2_super *osb,
 		     int ex)
 {
-	int status;
+	int status = 0;
 	int level = ex ? LKM_EXMODE : LKM_PRMODE;
 	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
 	struct buffer_head *bh;
@@ -1794,6 +1817,9 @@
 	if (ocfs2_is_hard_readonly(osb))
 		return -EROFS;
 
+	if (ocfs2_mount_local(osb))
+		goto bail;
+
 	status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
 	if (status < 0) {
 		mlog_errno(status);
@@ -1832,7 +1858,8 @@
 	int level = ex ? LKM_EXMODE : LKM_PRMODE;
 	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
 
-	ocfs2_cluster_unlock(osb, lockres, level);
+	if (!ocfs2_mount_local(osb))
+		ocfs2_cluster_unlock(osb, lockres, level);
 }
 
 int ocfs2_rename_lock(struct ocfs2_super *osb)
@@ -1843,6 +1870,9 @@
 	if (ocfs2_is_hard_readonly(osb))
 		return -EROFS;
 
+	if (ocfs2_mount_local(osb))
+		return 0;
+
 	status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
 	if (status < 0)
 		mlog_errno(status);
@@ -1854,7 +1884,8 @@
 {
 	struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
 
-	ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
+	if (!ocfs2_mount_local(osb))
+		ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
 }
 
 int ocfs2_dentry_lock(struct dentry *dentry, int ex)
@@ -1869,6 +1900,9 @@
 	if (ocfs2_is_hard_readonly(osb))
 		return -EROFS;
 
+	if (ocfs2_mount_local(osb))
+		return 0;
+
 	ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
 	if (ret < 0)
 		mlog_errno(ret);
@@ -1882,7 +1916,8 @@
 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
-	ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
+	if (!ocfs2_mount_local(osb))
+		ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
 }
 
 /* Reference counting of the dlm debug structure. We want this because
@@ -2145,12 +2180,15 @@
 
 int ocfs2_dlm_init(struct ocfs2_super *osb)
 {
-	int status;
+	int status = 0;
 	u32 dlm_key;
-	struct dlm_ctxt *dlm;
+	struct dlm_ctxt *dlm = NULL;
 
 	mlog_entry_void();
 
+	if (ocfs2_mount_local(osb))
+		goto local;
+
 	status = ocfs2_dlm_init_debug(osb);
 	if (status < 0) {
 		mlog_errno(status);
@@ -2178,11 +2216,12 @@
 		goto bail;
 	}
 
+	dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
+
+local:
 	ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
 	ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
 
-	dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
-
 	osb->dlm = dlm;
 
 	status = 0;
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
index cbfd45a..8fc52d6 100644
--- a/fs/ocfs2/heartbeat.c
+++ b/fs/ocfs2/heartbeat.c
@@ -154,6 +154,9 @@
 {
 	int status;
 
+	if (ocfs2_mount_local(osb))
+		return 0;
+
 	status = o2hb_register_callback(&osb->osb_hb_down);
 	if (status < 0) {
 		mlog_errno(status);
@@ -172,6 +175,9 @@
 {
 	int status;
 
+	if (ocfs2_mount_local(osb))
+		return;
+
 	status = o2hb_unregister_callback(&osb->osb_hb_down);
 	if (status < 0)
 		mlog_errno(status);
@@ -186,6 +192,9 @@
 	int ret;
 	char *argv[5], *envp[3];
 
+	if (ocfs2_mount_local(osb))
+		return;
+
 	if (!osb->uuid_str) {
 		/* This can happen if we don't get far enough in mount... */
 		mlog(0, "No UUID with which to stop heartbeat!\n\n");
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 42e361f..e4d9149 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -423,7 +423,8 @@
 	 * cluster lock before trusting anything anyway.
 	 */
 	can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
-		&& !(args->fi_flags & OCFS2_FI_FLAG_NOLOCK);
+		&& !(args->fi_flags & OCFS2_FI_FLAG_NOLOCK)
+		&& !ocfs2_mount_local(osb);
 
 	/*
 	 * To maintain backwards compatibility with older versions of
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 1d7f4ab..825cb0a 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -144,8 +144,10 @@
 			ocfs2_abort(osb->sb, "Detected aborted journal");
 			handle = ERR_PTR(-EROFS);
 		}
-	} else
-		atomic_inc(&(osb->journal->j_num_trans));
+	} else {
+		if (!ocfs2_mount_local(osb))
+			atomic_inc(&(osb->journal->j_num_trans));
+	}
 
 	return handle;
 }
@@ -507,9 +509,23 @@
 
 	BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
 
-	status = ocfs2_journal_toggle_dirty(osb, 0);
-	if (status < 0)
-		mlog_errno(status);
+	if (ocfs2_mount_local(osb)) {
+		journal_lock_updates(journal->j_journal);
+		status = journal_flush(journal->j_journal);
+		journal_unlock_updates(journal->j_journal);
+		if (status < 0)
+			mlog_errno(status);
+	}
+
+	if (status == 0) {
+		/*
+		 * Do not toggle if flush was unsuccessful otherwise
+		 * will leave dirty metadata in a "clean" journal
+		 */
+		status = ocfs2_journal_toggle_dirty(osb, 0);
+		if (status < 0)
+			mlog_errno(status);
+	}
 
 	/* Shutdown the kernel journal system */
 	journal_destroy(journal->j_journal);
@@ -549,7 +565,7 @@
 	}
 }
 
-int ocfs2_journal_load(struct ocfs2_journal *journal)
+int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
 {
 	int status = 0;
 	struct ocfs2_super *osb;
@@ -576,14 +592,18 @@
 	}
 
 	/* Launch the commit thread */
-	osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt");
-	if (IS_ERR(osb->commit_task)) {
-		status = PTR_ERR(osb->commit_task);
+	if (!local) {
+		osb->commit_task = kthread_run(ocfs2_commit_thread, osb,
+					       "ocfs2cmt");
+		if (IS_ERR(osb->commit_task)) {
+			status = PTR_ERR(osb->commit_task);
+			osb->commit_task = NULL;
+			mlog(ML_ERROR, "unable to launch ocfs2commit thread, "
+			     "error=%d", status);
+			goto done;
+		}
+	} else
 		osb->commit_task = NULL;
-		mlog(ML_ERROR, "unable to launch ocfs2commit thread, error=%d",
-		     status);
-		goto done;
-	}
 
 done:
 	mlog_exit(status);
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 899112a..e121636 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -157,7 +157,7 @@
 void   ocfs2_journal_shutdown(struct ocfs2_super *osb);
 int    ocfs2_journal_wipe(struct ocfs2_journal *journal,
 			  int full);
-int    ocfs2_journal_load(struct ocfs2_journal *journal);
+int    ocfs2_journal_load(struct ocfs2_journal *journal, int local);
 int    ocfs2_check_journals_nolocks(struct ocfs2_super *osb);
 void   ocfs2_recovery_thread(struct ocfs2_super *osb,
 			     int node_num);
@@ -174,6 +174,9 @@
 {
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
+	if (ocfs2_mount_local(osb))
+		return;
+
 	if (!ocfs2_inode_fully_checkpointed(inode)) {
 		/* WARNING: This only kicks off a single
 		 * checkpoint. If someone races you and adds more
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 69f85ae..51b0204 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -83,10 +83,12 @@
 int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	int ret = 0, lock_level = 0;
+	struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
 
 	/* We don't want to support shared writable mappings yet. */
-	if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
-	    && ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
+	if (!ocfs2_mount_local(osb) &&
+	    ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
+	    ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
 		mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
 		/* This is -EINVAL because generic_file_readonly_mmap
 		 * returns it in a similar situation. */
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 21db45d..9637039 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -587,9 +587,11 @@
 	}
 
 	ocfs2_inode_set_new(osb, inode);
-	status = ocfs2_create_new_inode_locks(inode);
-	if (status < 0)
-		mlog_errno(status);
+	if (!ocfs2_mount_local(osb)) {
+		status = ocfs2_create_new_inode_locks(inode);
+		if (status < 0)
+			mlog_errno(status);
+	}
 
 	status = 0; /* error in ocfs2_create_new_inode_locks is not
 		     * critical */
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index b767fd7..db8e77c 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -349,6 +349,11 @@
 	return ret;
 }
 
+static inline int ocfs2_mount_local(struct ocfs2_super *osb)
+{
+	return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT);
+}
+
 #define OCFS2_IS_VALID_DINODE(ptr)					\
 	(!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
 
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 3330a5d..b5c6856 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -86,7 +86,7 @@
 	OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
 
 #define OCFS2_FEATURE_COMPAT_SUPP	0
-#define OCFS2_FEATURE_INCOMPAT_SUPP	0
+#define OCFS2_FEATURE_INCOMPAT_SUPP	OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT
 #define OCFS2_FEATURE_RO_COMPAT_SUPP	0
 
 /*
@@ -96,6 +96,18 @@
  */
 #define OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV	0x0002
 
+/*
+ * tunefs sets this incompat flag before starting the resize and clears it
+ * at the end. This flag protects users from inadvertently mounting the fs
+ * after an aborted run without fsck-ing.
+ */
+#define OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG    0x0004
+
+/* Used to denote a non-clustered volume */
+#define OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT	0x0008
+
+/* Support for sparse allocation in b-trees */
+#define OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC	0x0010
 
 /*
  * Flags on ocfs2_dinode.i_flags
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 4bf3954..a6d2f8c 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -508,6 +508,27 @@
 	return status;
 }
 
+static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+{
+	if (ocfs2_mount_local(osb)) {
+		if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+			mlog(ML_ERROR, "Cannot heartbeat on a locally "
+			     "mounted device.\n");
+			return -EINVAL;
+		}
+	}
+
+	if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+		if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb)) {
+			mlog(ML_ERROR, "Heartbeat has to be started to mount "
+			     "a read-write clustered device.\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct dentry *root;
@@ -516,16 +537,24 @@
 	struct inode *inode = NULL;
 	struct ocfs2_super *osb = NULL;
 	struct buffer_head *bh = NULL;
+	char nodestr[8];
 
 	mlog_entry("%p, %p, %i", sb, data, silent);
 
-	/* for now we only have one cluster/node, make sure we see it
-	 * in the heartbeat universe */
-	if (!o2hb_check_local_node_heartbeating()) {
+	if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
 		status = -EINVAL;
 		goto read_super_error;
 	}
 
+	/* for now we only have one cluster/node, make sure we see it
+	 * in the heartbeat universe */
+	if (parsed_opt & OCFS2_MOUNT_HB_LOCAL) {
+		if (!o2hb_check_local_node_heartbeating()) {
+			status = -EINVAL;
+			goto read_super_error;
+		}
+	}
+
 	/* probe for superblock */
 	status = ocfs2_sb_probe(sb, &bh, &sector_size);
 	if (status < 0) {
@@ -541,11 +570,6 @@
 	}
 	brelse(bh);
 	bh = NULL;
-
-	if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
-		status = -EINVAL;
-		goto read_super_error;
-	}
 	osb->s_mount_opt = parsed_opt;
 
 	sb->s_magic = OCFS2_SUPER_MAGIC;
@@ -588,21 +612,16 @@
 	}
 
 	if (!ocfs2_is_hard_readonly(osb)) {
-		/* If this isn't a hard readonly mount, then we need
-		 * to make sure that heartbeat is in a valid state,
-		 * and that we mark ourselves soft readonly is -oro
-		 * was specified. */
-		if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
-			mlog(ML_ERROR, "No heartbeat for device (%s)\n",
-			     sb->s_id);
-			status = -EINVAL;
-			goto read_super_error;
-		}
-
 		if (sb->s_flags & MS_RDONLY)
 			ocfs2_set_ro_flag(osb, 0);
 	}
 
+	status = ocfs2_verify_heartbeat(osb);
+	if (status < 0) {
+		mlog_errno(status);
+		goto read_super_error;
+	}
+
 	osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
 						 ocfs2_debugfs_root);
 	if (!osb->osb_debug_root) {
@@ -635,9 +654,14 @@
 
 	ocfs2_complete_mount_recovery(osb);
 
-	printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %d, slot %d) "
+	if (ocfs2_mount_local(osb))
+		snprintf(nodestr, sizeof(nodestr), "local");
+	else
+		snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
+
+	printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d) "
 	       "with %s data mode.\n",
-	       osb->dev_str, osb->node_num, osb->slot_num,
+	       osb->dev_str, nodestr, osb->slot_num,
 	       osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" :
 	       "ordered");
 
@@ -999,7 +1023,11 @@
 
 	/* XXX hold a ref on the node while mounte?  easy enough, if
 	 * desirable. */
-	osb->node_num = o2nm_this_node();
+	if (ocfs2_mount_local(osb))
+		osb->node_num = 0;
+	else
+		osb->node_num = o2nm_this_node();
+
 	if (osb->node_num == O2NM_MAX_NODES) {
 		mlog(ML_ERROR, "could not find this host's node number\n");
 		status = -ENOENT;
@@ -1084,6 +1112,9 @@
 		goto leave;
 	}
 
+	if (ocfs2_mount_local(osb))
+		goto leave;
+
 	/* This should be sent *after* we recovered our journal as it
 	 * will cause other nodes to unmark us as needing
 	 * recovery. However, we need to send it *before* dropping the
@@ -1114,6 +1145,7 @@
 {
 	int tmp;
 	struct ocfs2_super *osb = NULL;
+	char nodestr[8];
 
 	mlog_entry("(0x%p)\n", sb);
 
@@ -1177,8 +1209,13 @@
 
 	atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
 
-	printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %d)\n",
-	       osb->dev_str, osb->node_num);
+	if (ocfs2_mount_local(osb))
+		snprintf(nodestr, sizeof(nodestr), "local");
+	else
+		snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
+
+	printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n",
+	       osb->dev_str, nodestr);
 
 	ocfs2_delete_osb(osb);
 	kfree(osb);
@@ -1536,6 +1573,7 @@
 {
 	int status = 0;
 	int dirty;
+	int local;
 	struct ocfs2_dinode *local_alloc = NULL; /* only used if we
 						  * recover
 						  * ourselves. */
@@ -1563,8 +1601,10 @@
 		     "recovering volume.\n");
 	}
 
+	local = ocfs2_mount_local(osb);
+
 	/* will play back anything left in the journal. */
-	ocfs2_journal_load(osb->journal);
+	ocfs2_journal_load(osb->journal, local);
 
 	if (dirty) {
 		/* recover my local alloc if we didn't unmount cleanly. */
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index 5b4dca7..0315a8b 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -1000,6 +1000,9 @@
 {
 	int status = 0;
 
+	if (ocfs2_mount_local(osb))
+		return 0;
+
 	status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE,
 					osb->net_key,
 					sizeof(struct ocfs2_response_msg),
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index dc3e580..92ea774 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -47,6 +47,7 @@
 #include <linux/vmalloc.h>
 #include <linux/crash_dump.h>
 #include <linux/pid_namespace.h>
+#include <linux/compile.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -253,8 +254,15 @@
 {
 	int len;
 
-	len = sprintf(page, linux_banner,
-		utsname()->release, utsname()->version);
+	/* FIXED STRING! Don't touch! */
+	len = snprintf(page, PAGE_SIZE,
+		"%s version %s"
+		" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+		" (" LINUX_COMPILER ")"
+		" %s\n",
+		utsname()->sysname,
+		utsname()->release,
+		utsname()->version);
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
diff --git a/include/asm-arm/arch-pnx4008/i2c.h b/include/asm-arm/arch-pnx4008/i2c.h
new file mode 100644
index 0000000..92e8d65
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/i2c.h
@@ -0,0 +1,67 @@
+/*
+ * PNX4008-specific tweaks for I2C IP3204 block
+ *
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARCH_I2C_H__
+#define __ASM_ARCH_I2C_H__
+
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+
+enum {
+	mstatus_tdi = 0x00000001,
+	mstatus_afi = 0x00000002,
+	mstatus_nai = 0x00000004,
+	mstatus_drmi = 0x00000008,
+	mstatus_active = 0x00000020,
+	mstatus_scl = 0x00000040,
+	mstatus_sda = 0x00000080,
+	mstatus_rff = 0x00000100,
+	mstatus_rfe = 0x00000200,
+	mstatus_tff = 0x00000400,
+	mstatus_tfe = 0x00000800,
+};
+
+enum {
+	mcntrl_tdie = 0x00000001,
+	mcntrl_afie = 0x00000002,
+	mcntrl_naie = 0x00000004,
+	mcntrl_drmie = 0x00000008,
+	mcntrl_daie = 0x00000020,
+	mcntrl_rffie = 0x00000040,
+	mcntrl_tffie = 0x00000080,
+	mcntrl_reset = 0x00000100,
+	mcntrl_cdbmode = 0x00000400,
+};
+
+enum {
+	rw_bit = 1 << 0,
+	start_bit = 1 << 8,
+	stop_bit = 1 << 9,
+};
+
+#define I2C_REG_RX(a)	((a)->ioaddr)		/* Rx FIFO reg (RO) */
+#define I2C_REG_TX(a)	((a)->ioaddr)		/* Tx FIFO reg (WO) */
+#define I2C_REG_STS(a)	((a)->ioaddr + 0x04)	/* Status reg (RO) */
+#define I2C_REG_CTL(a)	((a)->ioaddr + 0x08)	/* Ctl reg */
+#define I2C_REG_CKL(a)	((a)->ioaddr + 0x0c)	/* Clock divider low */
+#define I2C_REG_CKH(a)	((a)->ioaddr + 0x10)	/* Clock divider high */
+#define I2C_REG_ADR(a)	((a)->ioaddr + 0x14)	/* I2C address */
+#define I2C_REG_RFL(a)	((a)->ioaddr + 0x18)	/* Rx FIFO level (RO) */
+#define I2C_REG_TFL(a)	((a)->ioaddr + 0x1c)	/* Tx FIFO level (RO) */
+#define I2C_REG_RXB(a)	((a)->ioaddr + 0x20)	/* Num of bytes Rx-ed (RO) */
+#define I2C_REG_TXB(a)	((a)->ioaddr + 0x24)	/* Num of bytes Tx-ed (RO) */
+#define I2C_REG_TXS(a)	((a)->ioaddr + 0x28)	/* Tx slave FIFO (RO) */
+#define I2C_REG_STFL(a)	((a)->ioaddr + 0x2c)	/* Tx slave FIFO level (RO) */
+
+#define HCLK_MHZ		13
+#define I2C_CHIP_NAME		"PNX4008-I2C"
+
+#endif				/* __ASM_ARCH_I2C_H___ */
diff --git a/include/asm-avr32/arch-at32ap/at32ap7000.h b/include/asm-avr32/arch-at32ap/at32ap7000.h
new file mode 100644
index 0000000..ba85e04
--- /dev/null
+++ b/include/asm-avr32/arch-at32ap/at32ap7000.h
@@ -0,0 +1,33 @@
+/*
+ * Pin definitions for AT32AP7000.
+ *
+ * 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 __ASM_ARCH_AT32AP7000_H__
+#define __ASM_ARCH_AT32AP7000_H__
+
+#define GPIO_PERIPH_A	0
+#define GPIO_PERIPH_B	1
+
+#define NR_GPIO_CONTROLLERS	4
+
+/*
+ * Pin numbers identifying specific GPIO pins on the chip. They can
+ * also be converted to IRQ numbers by passing them through
+ * gpio_to_irq().
+ */
+#define GPIO_PIOA_BASE	(0)
+#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_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))
+
+#endif /* __ASM_ARCH_AT32AP7000_H__ */
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index a39b3e9..b120ee0 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -21,10 +21,7 @@
 struct platform_device *at32_add_device_usart(unsigned int id);
 
 struct eth_platform_data {
-	u8	valid;
-	u8	mii_phy_addr;
 	u8	is_rmii;
-	u8	hw_addr[6];
 };
 struct platform_device *
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
diff --git a/include/asm-avr32/arch-at32ap/portmux.h b/include/asm-avr32/arch-at32ap/portmux.h
index 4d50421..83c6905 100644
--- a/include/asm-avr32/arch-at32ap/portmux.h
+++ b/include/asm-avr32/arch-at32ap/portmux.h
@@ -7,10 +7,20 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASM_AVR32_AT32_PORTMUX_H__
-#define __ASM_AVR32_AT32_PORTMUX_H__
+#ifndef __ASM_ARCH_PORTMUX_H__
+#define __ASM_ARCH_PORTMUX_H__
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-		      unsigned int function_id);
+/*
+ * Set up pin multiplexing, called from board init only.
+ *
+ * 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 */
 
-#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */
+void at32_select_periph(unsigned int pin, unsigned int periph,
+			unsigned long flags);
+void at32_select_gpio(unsigned int pin, unsigned long flags);
+
+#endif /* __ASM_ARCH_PORTMUX_H__ */
diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h
index 0580b5d..5c01e27 100644
--- a/include/asm-avr32/dma-mapping.h
+++ b/include/asm-avr32/dma-mapping.h
@@ -109,7 +109,7 @@
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
 	       enum dma_data_direction direction)
 {
-	dma_cache_sync(cpu_addr, size, direction);
+	dma_cache_sync(dev, cpu_addr, size, direction);
 	return virt_to_bus(cpu_addr);
 }
 
@@ -211,7 +211,7 @@
 
 		sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
 		virt = page_address(sg[i].page) + sg[i].offset;
-		dma_cache_sync(virt, sg[i].length, direction);
+		dma_cache_sync(dev, virt, sg[i].length, direction);
 	}
 
 	return nents;
@@ -256,14 +256,14 @@
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 			size_t size, enum dma_data_direction direction)
 {
-	dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+	dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
 static inline void
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
 			   size_t size, enum dma_data_direction direction)
 {
-	dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+	dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
 /**
@@ -286,7 +286,7 @@
 	int i;
 
 	for (i = 0; i < nents; i++) {
-		dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+		dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
 			       sg[i].length, direction);
 	}
 }
@@ -298,7 +298,7 @@
 	int i;
 
 	for (i = 0; i < nents; i++) {
-		dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+		dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
 			       sg[i].length, direction);
 	}
 }
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 6e9fceb..7437cca 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -242,6 +242,7 @@
   	*(.initcall4s.init)						\
   	*(.initcall5.init)						\
   	*(.initcall5s.init)						\
+	*(.initcallrootfs.init)						\
   	*(.initcall6.init)						\
   	*(.initcall6s.init)						\
   	*(.initcall7.init)						\
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 5679d49..609a389 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -100,6 +100,8 @@
 
 #define MSR_P6_PERFCTR0		0xc1
 #define MSR_P6_PERFCTR1		0xc2
+#define MSR_FSB_FREQ		0xcd
+
 
 #define MSR_IA32_BBL_CR_CTL		0x119
 
@@ -130,6 +132,9 @@
 #define MSR_IA32_PERF_STATUS		0x198
 #define MSR_IA32_PERF_CTL		0x199
 
+#define MSR_IA32_MPERF			0xE7
+#define MSR_IA32_APERF			0xE8
+
 #define MSR_IA32_THERM_CONTROL		0x19a
 #define MSR_IA32_THERM_INTERRUPT	0x19b
 #define MSR_IA32_THERM_STATUS		0x19c
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 55a0152..432653d 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -5,6 +5,7 @@
  */
 #include <linux/types.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
 
 #define COMPAT_USER_HZ	100
 
diff --git a/include/asm-mips/mach-ip27/irq.h b/include/asm-mips/mach-ip27/irq.h
index 806213c..25f0c3f 100644
--- a/include/asm-mips/mach-ip27/irq.h
+++ b/include/asm-mips/mach-ip27/irq.h
@@ -10,8 +10,6 @@
 #ifndef __ASM_MACH_IP27_IRQ_H
 #define __ASM_MACH_IP27_IRQ_H
 
-#include <asm/sn/arch.h>
-
 /*
  * A hardwired interrupt number is completly stupid for this system - a
  * large configuration might have thousands if not tenthousands of
diff --git a/include/asm-mips/mach-ip27/topology.h b/include/asm-mips/mach-ip27/topology.h
index a13b715..44790fd 100644
--- a/include/asm-mips/mach-ip27/topology.h
+++ b/include/asm-mips/mach-ip27/topology.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_MACH_TOPOLOGY_H
 #define _ASM_MACH_TOPOLOGY_H	1
 
-#include <asm/sn/arch.h>
 #include <asm/sn/hub.h>
 #include <asm/mmzone.h>
 
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index c4d68be..7f0f120 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -187,4 +187,10 @@
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
+/* Chances are this interrupt is wired PC-style ...  */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return channel ? 15 : 14;
+}
+
 #endif /* _ASM_PCI_H */
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 30bf555..8a1f2b6 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -82,6 +82,14 @@
 
 extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
 
+extern NORET_TYPE void die(const char *, struct pt_regs *);
+
+static inline void die_if_kernel(const char *str, struct pt_regs *regs)
+{
+	if (unlikely(!user_mode(regs)))
+		die(str, regs);
+}
+
 #endif
 
 #endif /* _ASM_PTRACE_H */
diff --git a/include/asm-mips/sn/arch.h b/include/asm-mips/sn/arch.h
index 51174af..da523de 100644
--- a/include/asm-mips/sn/arch.h
+++ b/include/asm-mips/sn/arch.h
@@ -18,7 +18,6 @@
 #endif
 
 typedef u64	hubreg_t;
-typedef u64	nic_t;
 
 #define cputonasid(cpu)			(cpu_data[(cpu)].p_nasid)
 #define cputoslice(cpu)			(cpu_data[(cpu)].p_slice)
diff --git a/include/asm-mips/sn/klconfig.h b/include/asm-mips/sn/klconfig.h
index 15d70ca..82aeb9e 100644
--- a/include/asm-mips/sn/klconfig.h
+++ b/include/asm-mips/sn/klconfig.h
@@ -61,6 +61,8 @@
 #endif /* CONFIG_SGI_IP35 */
 #endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */
 
+typedef u64  nic_t;
+
 #define KLCFGINFO_MAGIC	0xbeedbabe
 
 typedef s32 klconf_off_t;
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 9428057..5e1289c 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -19,7 +19,6 @@
 #include <asm/barrier.h>
 #include <asm/cpu-features.h>
 #include <asm/dsp.h>
-#include <asm/ptrace.h>
 #include <asm/war.h>
 
 
@@ -336,14 +335,6 @@
 extern unsigned long ebase;
 extern void per_cpu_trap_init(void);
 
-extern NORET_TYPE void die(const char *, struct pt_regs *);
-
-static inline void die_if_kernel(const char *str, struct pt_regs *regs)
-{
-	if (unlikely(!user_mode(regs)))
-		die(str, regs);
-}
-
 extern int stop_a_enabled;
 
 /*
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 1e63738..703970f 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -17,7 +17,6 @@
 header-y += poll.h
 header-y += shmparam.h
 header-y += sockios.h
-header-y += spu_info.h
 header-y += ucontext.h
 header-y += ioctl.h
 header-y += linkage.h
@@ -37,6 +36,7 @@
 unifdef-y += ptrace.h
 unifdef-y += seccomp.h
 unifdef-y += signal.h
+unifdef-y += spu_info.h
 unifdef-y += termios.h
 unifdef-y += types.h
 unifdef-y += unistd.h
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index 0288144..8f757f6 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -209,7 +209,7 @@
 
 #ifdef __powerpc64__
 static inline __attribute__((const))
-int __ilog2_u64(u32 n)
+int __ilog2_u64(u64 n)
 {
 	int bit;
 	asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n));
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index 978b2c7..7095688 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -13,36 +13,39 @@
 
 #ifndef __ASSEMBLY__
 
-struct bug_entry {
-	unsigned long	bug_addr;
-	long		line;
-	const char	*file;
-	const char	*function;
-};
-
-struct bug_entry *find_bug(unsigned long bugaddr);
-
-/*
- * If this bit is set in the line number it means that the trap
- * is for WARN_ON rather than BUG or BUG_ON.
- */
-#define BUG_WARNING_TRAP	0x1000000
-
 #ifdef CONFIG_BUG
 
+/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
+   sizeof(struct bug_entry), respectively */
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define _EMIT_BUG_ENTRY				\
+	".section __bug_table,\"a\"\n"		\
+	"2:\t" PPC_LONG "1b, %0\n"		\
+	"\t.short %1, %2\n"			\
+	".org 2b+%3\n"				\
+	".previous\n"
+#else
+#define _EMIT_BUG_ENTRY				\
+	".section __bug_table,\"a\"\n"		\
+	"2:\t" PPC_LONG "1b\n"			\
+	"\t.short %2\n"				\
+	".org 2b+%3\n"				\
+	".previous\n"
+#endif
+
 /*
  * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
  * optimisations. However depending on the complexity of the condition
  * some compiler versions may not produce optimal results.
  */
 
-#define BUG() do {							 \
-	__asm__ __volatile__(						 \
-		"1:	twi 31,0,0\n"					 \
-		".section __bug_table,\"a\"\n"				 \
-		"\t"PPC_LONG"	1b,%0,%1,%2\n"				 \
-		".previous"						 \
-		: : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+#define BUG() do {						\
+	__asm__ __volatile__(					\
+		"1:	twi 31,0,0\n"				\
+		_EMIT_BUG_ENTRY					\
+		: : "i" (__FILE__), "i" (__LINE__),		\
+		    "i" (0), "i"  (sizeof(struct bug_entry)));	\
+	for(;;) ;						\
 } while (0)
 
 #define BUG_ON(x) do {						\
@@ -51,23 +54,21 @@
 			BUG();					\
 	} else {						\
 		__asm__ __volatile__(				\
-		"1:	"PPC_TLNEI"	%0,0\n"			\
-		".section __bug_table,\"a\"\n"			\
-		"\t"PPC_LONG"	1b,%1,%2,%3\n"			\
-		".previous"					\
-		: : "r" ((long)(x)), "i" (__LINE__),		\
-		    "i" (__FILE__), "i" (__FUNCTION__));	\
+		"1:	"PPC_TLNEI"	%4,0\n"			\
+		_EMIT_BUG_ENTRY					\
+		: : "i" (__FILE__), "i" (__LINE__), "i" (0),	\
+		  "i" (sizeof(struct bug_entry)),		\
+		  "r" ((long)(x)));				\
 	}							\
 } while (0)
 
 #define __WARN() do {						\
 	__asm__ __volatile__(					\
 		"1:	twi 31,0,0\n"				\
-		".section __bug_table,\"a\"\n"			\
-		"\t"PPC_LONG"	1b,%0,%1,%2\n"			\
-		".previous"					\
-		: : "i" (__LINE__ + BUG_WARNING_TRAP),		\
-		    "i" (__FILE__), "i" (__FUNCTION__));	\
+		_EMIT_BUG_ENTRY					\
+		: : "i" (__FILE__), "i" (__LINE__),		\
+		  "i" (BUGFLAG_WARNING),			\
+		  "i" (sizeof(struct bug_entry)));		\
 } while (0)
 
 #define WARN_ON(x) ({						\
@@ -77,13 +78,12 @@
 			__WARN();				\
 	} else {						\
 		__asm__ __volatile__(				\
-		"1:	"PPC_TLNEI"	%0,0\n"			\
-		".section __bug_table,\"a\"\n"			\
-		"\t"PPC_LONG"	1b,%1,%2,%3\n"			\
-		".previous"					\
-		: : "r" (__ret_warn_on),			\
-		    "i" (__LINE__ + BUG_WARNING_TRAP),		\
-		    "i" (__FILE__), "i" (__FUNCTION__));	\
+		"1:	"PPC_TLNEI"	%4,0\n"			\
+		_EMIT_BUG_ENTRY					\
+		: : "i" (__FILE__), "i" (__LINE__),		\
+		  "i" (BUGFLAG_WARNING),			\
+		  "i" (sizeof(struct bug_entry)),		\
+		  "r" (__ret_warn_on));				\
 	}							\
 	unlikely(__ret_warn_on);				\
 })
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 6fe5c9d..7384b80 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -126,6 +126,7 @@
 #define CPU_FTR_NODSISRALIGN		ASM_CONST(0x0000000000100000)
 #define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
+#define CPU_FTR_FPU_UNAVAILABLE		ASM_CONST(0x0000000000800000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -152,6 +153,7 @@
 #define CPU_FTR_PURR			LONG_ASM_CONST(0x0000400000000000)
 #define CPU_FTR_CELL_TB_BUG		LONG_ASM_CONST(0x0000800000000000)
 #define CPU_FTR_SPURR			LONG_ASM_CONST(0x0001000000000000)
+#define CPU_FTR_DSCR			LONG_ASM_CONST(0x0002000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -295,6 +297,9 @@
 #define CPU_FTRS_E300	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_COMMON)
+#define CPU_FTRS_E300C2	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
 #define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
 #define CPU_FTRS_8XX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
@@ -330,13 +335,14 @@
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE)
+	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
+	    CPU_FTR_DSCR)
 #define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \
-	    CPU_FTR_SPURR | CPU_FTR_REAL_LE)
+	    CPU_FTR_SPURR | CPU_FTR_REAL_LE | CPU_FTR_DSCR)
 #define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -364,7 +370,8 @@
 	    CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 |
 	    CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 |
 	    CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
-	    CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 |
+	    CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
+	    CPU_FTRS_CLASSIC32 |
 #else
 	    CPU_FTRS_GENERIC_32 |
 #endif
@@ -403,7 +410,8 @@
 	    CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 &
 	    CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 &
 	    CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
-	    CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 &
+	    CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
+	    CPU_FTRS_CLASSIC32 &
 #else
 	    CPU_FTRS_GENERIC_32 &
 #endif
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index fd4a5f5..d7a1bc1 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -20,8 +20,7 @@
 #ifndef _ASM_POWERPC_DCR_NATIVE_H
 #define _ASM_POWERPC_DCR_NATIVE_H
 #ifdef __KERNEL__
-
-#include <asm/reg.h>
+#ifndef __ASSEMBLY__
 
 typedef struct {} dcr_host_t;
 
@@ -32,7 +31,41 @@
 #define dcr_read(host, dcr_n)		mfdcr(dcr_n)
 #define dcr_write(host, dcr_n, value)	mtdcr(dcr_n, value)
 
+/* Device Control Registers */
+void __mtdcr(int reg, unsigned int val);
+unsigned int __mfdcr(int reg);
+#define mfdcr(rn)						\
+	({unsigned int rval;					\
+	if (__builtin_constant_p(rn))				\
+		asm volatile("mfdcr %0," __stringify(rn)	\
+		              : "=r" (rval));			\
+	else							\
+		rval = __mfdcr(rn);				\
+	rval;})
 
+#define mtdcr(rn, v)						\
+do {								\
+	if (__builtin_constant_p(rn))				\
+		asm volatile("mtdcr " __stringify(rn) ",%0"	\
+			      : : "r" (v)); 			\
+	else							\
+		__mtdcr(rn, v);					\
+} while (0)
+
+/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
+#define mfdcri(base, reg)			\
+({						\
+	mtdcr(base ## _CFGADDR, base ## _ ## reg);	\
+	mfdcr(base ## _CFGDATA);			\
+})
+
+#define mtdcri(base, reg, data)			\
+do {						\
+	mtdcr(base ## _CFGADDR, base ## _ ## reg);	\
+	mtdcr(base ## _CFGDATA, data);		\
+} while (0)
+
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DCR_NATIVE_H */
 
diff --git a/include/asm-powerpc/dcr.h b/include/asm-powerpc/dcr.h
index 473f2c7..b66c5e6 100644
--- a/include/asm-powerpc/dcr.h
+++ b/include/asm-powerpc/dcr.h
@@ -20,6 +20,7 @@
 #ifndef _ASM_POWERPC_DCR_H
 #define _ASM_POWERPC_DCR_H
 #ifdef __KERNEL__
+#ifdef CONFIG_PPC_DCR
 
 #ifdef CONFIG_PPC_DCR_NATIVE
 #include <asm/dcr-native.h>
@@ -38,5 +39,6 @@
 				     unsigned int index);
 #endif /* CONFIG_PPC_MERGE */
 
+#endif /* CONFIG_PPC_DCR */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DCR_H */
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index d604863..9e4dd98 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -107,25 +107,6 @@
 
 #endif /* CONFIG_PPC64 */
 
-#define mask_irq(irq)						\
-	({							\
-	 	irq_desc_t *desc = get_irq_desc(irq);		\
-		if (desc->chip && desc->chip->disable)	\
-			desc->chip->disable(irq);		\
-	})
-#define unmask_irq(irq)						\
-	({							\
-	 	irq_desc_t *desc = get_irq_desc(irq);		\
-		if (desc->chip && desc->chip->enable)	\
-			desc->chip->enable(irq);		\
-	})
-#define ack_irq(irq)						\
-	({							\
-	 	irq_desc_t *desc = get_irq_desc(irq);		\
-		if (desc->chip && desc->chip->ack)	\
-			desc->chip->ack(irq);		\
-	})
-
 /*
  * interrupt-retrigger: should we handle this via lost interrupts and IPIs
  * or should we not care like we do now ? --BenH.
diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h
index 584fabf..e5f14b1 100644
--- a/include/asm-powerpc/module.h
+++ b/include/asm-powerpc/module.h
@@ -46,8 +46,6 @@
 	unsigned int num_bugs;
 };
 
-extern struct bug_entry *module_find_bug(unsigned long bugaddr);
-
 /*
  * Select ELF headers.
  * Make empty section for module_frob_arch_sections to expand.
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 7bb7f90..cb02c9d 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -31,12 +31,12 @@
 	int last_busno;
 
 	void __iomem *io_base_virt;
-	unsigned long io_base_phys;
+	resource_size_t io_base_phys;
 
 	/* Some machines have a non 1:1 mapping of
 	 * the PCI memory space in the CPU bus space
 	 */
-	unsigned long pci_mem_offset;
+	resource_size_t pci_mem_offset;
 	unsigned long pci_io_size;
 
 	struct pci_ops *ops;
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index 16f1331..ac656ee 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -143,8 +143,13 @@
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
 #define HAVE_PCI_MMAP	1
 
-#ifdef CONFIG_PPC64
-/* pci_unmap_{single,page} is not a nop, thus... */
+#if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE)
+/*
+ * For 64-bit kernels, pci_unmap_{single,page} is not a nop.
+ * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and
+ * so on are not nops.
+ * and thus...
+ */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
@@ -158,6 +163,20 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
+#else /* 32-bit && coherent */
+
+/* pci_unmap_{page,single} is a nop so... */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
+
+#endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */
+
+#ifdef CONFIG_PPC64
+
 /* The PCI address space does not equal the physical memory address
  * space (we have an IOMMU).  The IDE and SCSI device layers use
  * this boolean for bounce buffer decisions.
@@ -172,16 +191,8 @@
  */
 #define PCI_DMA_BUS_IS_PHYS     (1)
 
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-
 #endif /* CONFIG_PPC64 */
-	
+
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
 			struct pci_bus_region *region,
 			struct resource *res);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 6faae7b..a3631b1 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -143,6 +143,7 @@
 
 /* Special Purpose Registers (SPRNs)*/
 #define SPRN_CTR	0x009	/* Count Register */
+#define SPRN_DSCR	0x11
 #define SPRN_CTRLF	0x088
 #define SPRN_CTRLT	0x098
 #define   CTRL_CT	0xc0000000	/* current thread */
@@ -163,6 +164,7 @@
 #define SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
 #define SPRN_TBWL	0x11C	/* Time Base Lower Register (super, R/W) */
 #define SPRN_TBWU	0x11D	/* Time Base Upper Register (super, R/W) */
+#define SPRN_SPURR	0x134	/* Scaled PURR */
 #define SPRN_HIOR	0x137	/* 970 Hypervisor interrupt offset */
 #define SPRN_DBAT0L	0x219	/* Data BAT 0 Lower Register */
 #define SPRN_DBAT0U	0x218	/* Data BAT 0 Upper Register */
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
index 5a0c136..8eaa7b2 100644
--- a/include/asm-powerpc/rtas.h
+++ b/include/asm-powerpc/rtas.h
@@ -159,6 +159,7 @@
 
 extern void enter_rtas(unsigned long);
 extern int rtas_token(const char *service);
+extern int rtas_service_present(const char *service);
 extern int rtas_call(int token, int, int, int *, ...);
 extern void rtas_restart(char *cmd);
 extern void rtas_power_off(void);
@@ -221,8 +222,6 @@
 extern spinlock_t rtas_data_buf_lock;
 extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
 
-extern void rtas_stop_self(void);
-
 /* RMO buffer reserved for user-space RTAS use */
 extern unsigned long rtas_rmo_buf;
 
diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
index 6c955d0..4d35b84 100644
--- a/include/asm-ppc/pci-bridge.h
+++ b/include/asm-ppc/pci-bridge.h
@@ -20,8 +20,8 @@
 extern struct pci_controller* pcibios_alloc_controller(void);
 
 /* Helper function for setting up resources */
-extern void pci_init_resource(struct resource *res, unsigned long start,
-			      unsigned long end, int flags, char *name);
+extern void pci_init_resource(struct resource *res, resource_size_t start,
+			      resource_size_t end, int flags, char *name);
 
 /* Get the PCI host controller for a bus */
 extern struct pci_controller* pci_bus_to_hose(int bus);
@@ -50,12 +50,12 @@
 	int bus_offset;
 
 	void __iomem *io_base_virt;
-	unsigned long io_base_phys;
+	resource_size_t io_base_phys;
 
 	/* Some machines (PReP) have a non 1:1 mapping of
 	 * the PCI memory space in the CPU bus space
 	 */
-	unsigned long pci_mem_offset;
+	resource_size_t pci_mem_offset;
 
 	struct pci_ops *ops;
 	volatile unsigned int __iomem *cfg_addr;
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
index 11ffaaa..9d16202 100644
--- a/include/asm-ppc/pci.h
+++ b/include/asm-ppc/pci.h
@@ -61,6 +61,27 @@
  */
 #define PCI_DMA_BUS_IS_PHYS     (1)
 
+#ifdef CONFIG_NOT_COHERENT_CACHE
+/*
+ * pci_unmap_{page,single} are NOPs but pci_dma_sync_single_for_cpu()
+ * and so on are not, so...
+ */
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
+	dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
+	__u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
+	((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
+	(((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)			\
+	((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
+	(((PTR)->LEN_NAME) = (VAL))
+
+#else /* coherent */
+
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
@@ -69,6 +90,8 @@
 #define pci_unmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
+#endif /* CONFIG_NOT_COHERENT_CACHE */
+
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 602fbad..a263fc1e 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -9,41 +9,9 @@
 #ifndef __ASM_PPC_REG_BOOKE_H__
 #define __ASM_PPC_REG_BOOKE_H__
 
+#include <asm/dcr.h>
+
 #ifndef __ASSEMBLY__
-/* Device Control Registers */
-void __mtdcr(int reg, unsigned int val);
-unsigned int __mfdcr(int reg);
-#define mfdcr(rn)						\
-	({unsigned int rval;					\
-	if (__builtin_constant_p(rn))				\
-		asm volatile("mfdcr %0," __stringify(rn)	\
-		              : "=r" (rval));			\
-	else							\
-		rval = __mfdcr(rn);				\
-	rval;})
-
-#define mtdcr(rn, v)						\
-do {								\
-	if (__builtin_constant_p(rn))				\
-		asm volatile("mtdcr " __stringify(rn) ",%0"	\
-			      : : "r" (v)); 			\
-	else							\
-		__mtdcr(rn, v);					\
-} while (0)
-
-/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
-#define mfdcri(base, reg)			\
-({						\
-	mtdcr(base ## _CFGADDR, base ## _ ## reg);	\
-	mfdcr(base ## _CFGDATA);			\
-})
-
-#define mtdcri(base, reg, data)			\
-do {						\
-	mtdcr(base ## _CFGADDR, base ## _ ## reg);	\
-	mtdcr(base ## _CFGDATA, data);		\
-} while (0)
-
 /* Performance Monitor Registers */
 #define mfpmr(rn)	({unsigned int rval; \
 			asm volatile("mfpmr %0," __stringify(rn) \
diff --git a/include/asm-sh/atomic-irq.h b/include/asm-sh/atomic-irq.h
new file mode 100644
index 0000000..74f7943
--- /dev/null
+++ b/include/asm-sh/atomic-irq.h
@@ -0,0 +1,71 @@
+#ifndef __ASM_SH_ATOMIC_IRQ_H
+#define __ASM_SH_ATOMIC_IRQ_H
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+static inline void atomic_add(int i, atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*(long *)v += i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*(long *)v -= i;
+	local_irq_restore(flags);
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	unsigned long temp, flags;
+
+	local_irq_save(flags);
+	temp = *(long *)v;
+	temp += i;
+	*(long *)v = temp;
+	local_irq_restore(flags);
+
+	return temp;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	unsigned long temp, flags;
+
+	local_irq_save(flags);
+	temp = *(long *)v;
+	temp -= i;
+	*(long *)v = temp;
+	local_irq_restore(flags);
+
+	return temp;
+}
+
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*(long *)v &= ~mask;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*(long *)v |= mask;
+	local_irq_restore(flags);
+}
+
+#endif /* __ASM_SH_ATOMIC_IRQ_H */
diff --git a/include/asm-sh/atomic-llsc.h b/include/asm-sh/atomic-llsc.h
new file mode 100644
index 0000000..4b00b78
--- /dev/null
+++ b/include/asm-sh/atomic-llsc.h
@@ -0,0 +1,107 @@
+#ifndef __ASM_SH_ATOMIC_LLSC_H
+#define __ASM_SH_ATOMIC_LLSC_H
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+static inline void atomic_add(int i, atomic_t *v)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+"1:	movli.l @%2, %0		! atomic_add	\n"
+"	add	%1, %0				\n"
+"	movco.l	%0, @%2				\n"
+"	bf	1b				\n"
+	: "=&z" (tmp)
+	: "r" (i), "r" (&v->counter)
+	: "t");
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+"1:	movli.l @%2, %0		! atomic_sub	\n"
+"	sub	%1, %0				\n"
+"	movco.l	%0, @%2				\n"
+"	bf	1b				\n"
+	: "=&z" (tmp)
+	: "r" (i), "r" (&v->counter)
+	: "t");
+}
+
+/*
+ * SH-4A note:
+ *
+ * We basically get atomic_xxx_return() for free compared with
+ * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
+ * encoding, so the retval is automatically set without having to
+ * do any special work.
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	unsigned long temp;
+
+	__asm__ __volatile__ (
+"1:	movli.l @%2, %0		! atomic_add_return	\n"
+"	add	%1, %0					\n"
+"	movco.l	%0, @%2					\n"
+"	bf	1b					\n"
+"	synco						\n"
+	: "=&z" (temp)
+	: "r" (i), "r" (&v->counter)
+	: "t");
+
+	return temp;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	unsigned long temp;
+
+	__asm__ __volatile__ (
+"1:	movli.l @%2, %0		! atomic_sub_return	\n"
+"	sub	%1, %0					\n"
+"	movco.l	%0, @%2					\n"
+"	bf	1b					\n"
+"	synco						\n"
+	: "=&z" (temp)
+	: "r" (i), "r" (&v->counter)
+	: "t");
+
+	return temp;
+}
+
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+"1:	movli.l @%2, %0		! atomic_clear_mask	\n"
+"	and	%1, %0					\n"
+"	movco.l	%0, @%2					\n"
+"	bf	1b					\n"
+	: "=&z" (tmp)
+	: "r" (~mask), "r" (&v->counter)
+	: "t");
+}
+
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+"1:	movli.l @%2, %0		! atomic_set_mask	\n"
+"	or	%1, %0					\n"
+"	movco.l	%0, @%2					\n"
+"	bf	1b					\n"
+	: "=&z" (tmp)
+	: "r" (mask), "r" (&v->counter)
+	: "t");
+}
+
+#endif /* __ASM_SH_ATOMIC_LLSC_H */
diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h
index 28305c3..e12570b 100644
--- a/include/asm-sh/atomic.h
+++ b/include/asm-sh/atomic.h
@@ -17,119 +17,14 @@
 #include <linux/compiler.h>
 #include <asm/system.h>
 
-/*
- * To get proper branch prediction for the main line, we must branch
- * forward to code at the end of this object's .text section, then
- * branch back to restart the operation.
- */
-static inline void atomic_add(int i, atomic_t *v)
-{
 #ifdef CONFIG_CPU_SH4A
-	unsigned long tmp;
-
-	__asm__ __volatile__ (
-"1:	movli.l @%2, %0		! atomic_add	\n"
-"	add	%1, %0				\n"
-"	movco.l	%0, @%2				\n"
-"	bf	1b				\n"
-	: "=&z" (tmp)
-	: "r" (i), "r" (&v->counter)
-	: "t");
+#include <asm/atomic-llsc.h>
 #else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	*(long *)v += i;
-	local_irq_restore(flags);
+#include <asm/atomic-irq.h>
 #endif
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-#ifdef CONFIG_CPU_SH4A
-	unsigned long tmp;
-
-	__asm__ __volatile__ (
-"1:	movli.l @%2, %0		! atomic_sub	\n"
-"	sub	%1, %0				\n"
-"	movco.l	%0, @%2				\n"
-"	bf	1b				\n"
-	: "=&z" (tmp)
-	: "r" (i), "r" (&v->counter)
-	: "t");
-#else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	*(long *)v -= i;
-	local_irq_restore(flags);
-#endif
-}
-
-/*
- * SH-4A note:
- *
- * We basically get atomic_xxx_return() for free compared with
- * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
- * encoding, so the retval is automatically set without having to
- * do any special work.
- */
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	unsigned long temp;
-
-#ifdef CONFIG_CPU_SH4A
-	__asm__ __volatile__ (
-"1:	movli.l @%2, %0		! atomic_add_return	\n"
-"	add	%1, %0					\n"
-"	movco.l	%0, @%2					\n"
-"	bf	1b					\n"
-"	synco						\n"
-	: "=&z" (temp)
-	: "r" (i), "r" (&v->counter)
-	: "t");
-#else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	temp = *(long *)v;
-	temp += i;
-	*(long *)v = temp;
-	local_irq_restore(flags);
-#endif
-
-	return temp;
-}
 
 #define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
 
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	unsigned long temp;
-
-#ifdef CONFIG_CPU_SH4A
-	__asm__ __volatile__ (
-"1:	movli.l @%2, %0		! atomic_sub_return	\n"
-"	sub	%1, %0					\n"
-"	movco.l	%0, @%2					\n"
-"	bf	1b					\n"
-"	synco						\n"
-	: "=&z" (temp)
-	: "r" (i), "r" (&v->counter)
-	: "t");
-#else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	temp = *(long *)v;
-	temp -= i;
-	*(long *)v = temp;
-	local_irq_restore(flags);
-#endif
-
-	return temp;
-}
-
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
 #define atomic_inc_return(v) atomic_add_return(1,(v))
 
@@ -180,50 +75,6 @@
 }
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
-#ifdef CONFIG_CPU_SH4A
-	unsigned long tmp;
-
-	__asm__ __volatile__ (
-"1:	movli.l @%2, %0		! atomic_clear_mask	\n"
-"	and	%1, %0					\n"
-"	movco.l	%0, @%2					\n"
-"	bf	1b					\n"
-	: "=&z" (tmp)
-	: "r" (~mask), "r" (&v->counter)
-	: "t");
-#else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	*(long *)v &= ~mask;
-	local_irq_restore(flags);
-#endif
-}
-
-static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
-#ifdef CONFIG_CPU_SH4A
-	unsigned long tmp;
-
-	__asm__ __volatile__ (
-"1:	movli.l @%2, %0		! atomic_set_mask	\n"
-"	or	%1, %0					\n"
-"	movco.l	%0, @%2					\n"
-"	bf	1b					\n"
-	: "=&z" (tmp)
-	: "r" (mask), "r" (&v->counter)
-	: "t");
-#else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	*(long *)v |= mask;
-	local_irq_restore(flags);
-#endif
-}
-
 /* Atomic operations are already serializing on SH */
 #define smp_mb__before_atomic_dec()	barrier()
 #define smp_mb__after_atomic_dec()	barrier()
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index 1b4fc52..2f89dd0 100644
--- a/include/asm-sh/bug.h
+++ b/include/asm-sh/bug.h
@@ -1,19 +1,54 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
-
 #ifdef CONFIG_BUG
-/*
- * Tell the user there is some problem.
- */
-#define BUG() do { \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	*(volatile int *)0 = 0; \
+
+struct bug_frame {
+	unsigned short	opcode;
+	unsigned short	line;
+	const char	*file;
+	const char	*func;
+};
+
+struct pt_regs;
+
+extern void handle_BUG(struct pt_regs *);
+
+#define TRAPA_BUG_OPCODE	0xc33e	/* trapa #0x3e */
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#define BUG()						\
+do {							\
+	__asm__ __volatile__ (				\
+		".align	2\n\t"				\
+		".short	%O0\n\t"			\
+		".short	%O1\n\t"			\
+		".long	%O2\n\t"			\
+		".long	%O3\n\t"			\
+		:					\
+		: "n" (TRAPA_BUG_OPCODE),		\
+		  "i" (__LINE__), "X" (__FILE__),	\
+		  "X" (__FUNCTION__));			\
 } while (0)
 
+#else
+
+#define BUG()					\
+do {						\
+	__asm__ __volatile__ (			\
+		".align	2\n\t"			\
+		".short	%O0\n\t"		\
+		:				\
+		: "n" (TRAPA_BUG_OPCODE));	\
+} while (0)
+
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+
 #define HAVE_ARCH_BUG
-#endif
+
+#endif /* CONFIG_BUG */
 
 #include <asm-generic/bug.h>
 
-#endif
+#endif /* __ASM_SH_BUG_H */
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index 795047d..a294997 100644
--- a/include/asm-sh/bugs.h
+++ b/include/asm-sh/bugs.h
@@ -16,9 +16,8 @@
 
 static void __init check_bugs(void)
 {
-	extern char *get_cpu_subtype(void);
 	extern unsigned long loops_per_jiffy;
-	char *p= &init_utsname()->machine[2]; /* "sh" */
+	char *p = &init_utsname()->machine[2]; /* "sh" */
 
 	cpu_data->loops_per_jiffy = loops_per_jiffy;
 
@@ -40,6 +39,15 @@
 		*p++ = '4';
 		*p++ = 'a';
 		break;
+	case CPU_SH73180 ... CPU_SH7722:
+		*p++ = '4';
+		*p++ = 'a';
+		*p++ = 'l';
+		*p++ = '-';
+		*p++ = 'd';
+		*p++ = 's';
+		*p++ = 'p';
+		break;
 	default:
 		*p++ = '?';
 		*p++ = '!';
diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
index d44344c..4bc8357 100644
--- a/include/asm-sh/checksum.h
+++ b/include/asm-sh/checksum.h
@@ -34,25 +34,26 @@
  */
 
 asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
-					  int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr);
+					    int len, __wsum sum,
+					    int *src_err_ptr, int *dst_err_ptr);
 
 /*
  *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions. 
- *	
- *	If you use these functions directly please don't forget the 
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
  *	access_ok().
  */
-static __inline__
+static inline
 __wsum csum_partial_copy_nocheck(const void *src, void *dst,
-					int len, __wsum sum)
+				 int len, __wsum sum)
 {
-	return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+	return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
 }
 
-static __inline__
+static inline
 __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-						int len, __wsum sum, int *err_ptr)
+				   int len, __wsum sum, int *err_ptr)
 {
 	return csum_partial_copy_generic((__force const void *)src, dst,
 					len, sum, err_ptr, NULL);
@@ -62,7 +63,7 @@
  *	Fold a partial checksum
  */
 
-static __inline__ __sum16 csum_fold(__wsum sum)
+static inline __sum16 csum_fold(__wsum sum)
 {
 	unsigned int __dummy;
 	__asm__("swap.w %0, %1\n\t"
@@ -85,7 +86,7 @@
  *      i386 version by Jorge Cwik <jorge@laser.satlink.net>, adapted
  *      for linux by * Arnt Gulbrandsen.
  */
-static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
 {
 	unsigned int sum, __dummy0, __dummy1;
 
@@ -113,10 +114,10 @@
 	return	csum_fold(sum);
 }
 
-static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+					unsigned short len,
+					unsigned short proto,
+					__wsum sum)
 {
 #ifdef __LITTLE_ENDIAN__
 	unsigned long len_proto = (proto + len) << 8;
@@ -132,6 +133,7 @@
 		: "=r" (sum), "=r" (len_proto)
 		: "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum)
 		: "t");
+
 	return sum;
 }
 
@@ -139,30 +141,28 @@
  * computes the checksum of the TCP/UDP pseudo-header
  * returns a 16-bit checksum, already complemented
  */
-static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						       unsigned short len,
-						       unsigned short proto,
-						       __wsum sum)
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+					unsigned short len,
+					unsigned short proto,
+					__wsum sum)
 {
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 }
 
 /*
  * this routine is used for miscellaneous IP-like checksums, mainly
  * in icmp.c
  */
-
-static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
 {
-    return csum_fold (csum_partial(buff, len, 0));
+    return csum_fold(csum_partial(buff, len, 0));
 }
 
 #define _HAVE_ARCH_IPV6_CSUM
-#ifdef CONFIG_IPV6
-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
-					  const struct in6_addr *daddr,
-					  __u32 len, unsigned short proto,
-					  __wsum sum)
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+				      const struct in6_addr *daddr,
+				      __u32 len, unsigned short proto,
+				      __wsum sum)
 {
 	unsigned int __dummy;
 	__asm__("clrt\n\t"
@@ -187,22 +187,21 @@
 		"movt	%1\n\t"
 		"add	%1, %0\n"
 		: "=r" (sum), "=&r" (__dummy)
-		: "r" (saddr), "r" (daddr), 
+		: "r" (saddr), "r" (daddr),
 		  "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
 		: "t");
 
 	return csum_fold(sum);
 }
-#endif
 
-/* 
+/*
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ __wsum csum_and_copy_to_user (const void *src,
-						      void __user *dst,
-						      int len, __wsum sum,
-						      int *err_ptr)
+static inline __wsum csum_and_copy_to_user(const void *src,
+					   void __user *dst,
+					   int len, __wsum sum,
+					   int *err_ptr)
 {
 	if (access_ok(VERIFY_WRITE, dst, len))
 		return csum_partial_copy_generic((__force const void *)src,
diff --git a/include/asm-sh/cpu-sh4/cache.h b/include/asm-sh/cpu-sh4/cache.h
index 6e9c7e6..f92b20a 100644
--- a/include/asm-sh/cpu-sh4/cache.h
+++ b/include/asm-sh/cpu-sh4/cache.h
@@ -22,7 +22,7 @@
 #define CCR_CACHE_ICE	0x0100	/* Instruction Cache Enable */
 #define CCR_CACHE_ICI	0x0800	/* IC Invalidate */
 #define CCR_CACHE_IIX	0x8000	/* IC Index Enable */
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
+#ifndef CONFIG_CPU_SH4A
 #define CCR_CACHE_EMODE	0x80000000	/* EMODE Enable */
 #endif
 
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index ef2b9b1..602d061 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -10,7 +10,7 @@
 #ifndef __ASM_CPU_SH4_FREQ_H
 #define __ASM_CPU_SH4_FREQ_H
 
-#if defined(CONFIG_CPU_SUBTYPE_SH73180)
+#if defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7722)
 #define FRQCR		        0xa4150000
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define	FRQCR			0xffc80000
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 37ab0c1..8d0867b 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -67,7 +67,7 @@
 	if (dev->bus == &pci_bus_type)
 		return virt_to_bus(ptr);
 #endif
-	dma_cache_sync(ptr, size, dir);
+	dma_cache_sync(dev, ptr, size, dir);
 
 	return virt_to_bus(ptr);
 }
@@ -81,7 +81,7 @@
 
 	for (i = 0; i < nents; i++) {
 #if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
-		dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+		dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
 			       sg[i].length, dir);
 #endif
 		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
@@ -112,7 +112,7 @@
 	if (dev->bus == &pci_bus_type)
 		return;
 #endif
-	dma_cache_sync(bus_to_virt(dma_handle), size, dir);
+	dma_cache_sync(dev, bus_to_virt(dma_handle), size, dir);
 }
 
 static inline void dma_sync_single_range(struct device *dev,
@@ -124,7 +124,7 @@
 	if (dev->bus == &pci_bus_type)
 		return;
 #endif
-	dma_cache_sync(bus_to_virt(dma_handle) + offset, size, dir);
+	dma_cache_sync(dev, bus_to_virt(dma_handle) + offset, size, dir);
 }
 
 static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
@@ -134,7 +134,7 @@
 
 	for (i = 0; i < nelems; i++) {
 #if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
-		dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+		dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
 			       sg[i].length, dir);
 #endif
 		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index fd57608..bff965e 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -37,7 +37,8 @@
 # define ONCHIP_NR_IRQS 144
 #elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
       defined(CONFIG_CPU_SUBTYPE_SH73180) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7343)
+      defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7722)
 # define ONCHIP_NR_IRQS 109
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define ONCHIP_NR_IRQS 111
@@ -79,6 +80,8 @@
 # define OFFCHIP_NR_IRQS 16
 #elif defined(CONFIG_SH_7343_SOLUTION_ENGINE)
 # define OFFCHIP_NR_IRQS 12
+#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+# define OFFCHIP_NR_IRQS 14
 #elif defined(CONFIG_SH_UNKNOWN)
 # define OFFCHIP_NR_IRQS 16	/* Must also be last */
 #else
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index c84901d..036ca28 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -508,16 +508,50 @@
 extern void update_mmu_cache(struct vm_area_struct * vma,
 			     unsigned long address, pte_t pte);
 
-/* Encode and de-code a swap entry */
 /*
+ * Encode and de-code a swap entry
+ *
+ * Constraints:
+ *	_PAGE_FILE at bit 0
+ *	_PAGE_PRESENT at bit 8
+ *	_PAGE_PROTNONE at bit 9
+ *
+ * For the normal case, we encode the swap type into bits 0:7 and the
+ * swap offset into bits 10:30. For the 64-bit PTE case, we keep the
+ * preserved bits in the low 32-bits and use the upper 32 as the swap
+ * offset (along with a 5-bit type), following the same approach as x86
+ * PAE. This keeps the logic quite simple, and allows for a full 32
+ * PTE_FILE_MAX_BITS, as opposed to the 29-bits we're constrained with
+ * in the pte_low case.
+ *
+ * As is evident by the Alpha code, if we ever get a 64-bit unsigned
+ * long (swp_entry_t) to match up with the 64-bit PTEs, this all becomes
+ * much cleaner..
+ *
  * NOTE: We should set ZEROs at the position of _PAGE_PRESENT
  *       and _PAGE_PROTNONE bits
  */
-#define __swp_type(x)		((x).val & 0xff)
-#define __swp_offset(x)		((x).val >> 10)
-#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 10) })
-#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) >> 1 })
-#define __swp_entry_to_pte(x)	((pte_t) { (x).val << 1 })
+#ifdef CONFIG_X2TLB
+#define __swp_type(x)			((x).val & 0x1f)
+#define __swp_offset(x)			((x).val >> 5)
+#define __swp_entry(type, offset)	((swp_entry_t){ (type) | (offset) << 5})
+#define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
+#define __swp_entry_to_pte(x)		((pte_t){ 0, (x).val })
+
+/*
+ * Encode and decode a nonlinear file mapping entry
+ */
+#define pte_to_pgoff(pte)		((pte).pte_high)
+#define pgoff_to_pte(off)		((pte_t) { _PAGE_FILE, (off) })
+
+#define PTE_FILE_MAX_BITS		32
+#else
+#define __swp_type(x)			((x).val & 0xff)
+#define __swp_offset(x)			((x).val >> 10)
+#define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) <<10})
+
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 1 })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val << 1 })
 
 /*
  * Encode and decode a nonlinear file mapping entry
@@ -525,6 +559,7 @@
 #define PTE_FILE_MAX_BITS	29
 #define pte_to_pgoff(pte)	(pte_val(pte) >> 1)
 #define pgoff_to_pte(off)	((pte_t) { ((off) << 1) | _PAGE_FILE })
+#endif
 
 typedef pte_t *pte_addr_t;
 
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index 6f1dd7c..e29f2ab 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -27,6 +27,8 @@
 #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.
  *
@@ -52,8 +54,10 @@
 	CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
 
 	/* SH-4A types */
-	CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781,
-	CPU_SH7785,
+	CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+
+	/* SH4AL-DSP types */
+	CPU_SH73180, CPU_SH7343, CPU_SH7722,
 
 	/* Unknown subtype */
 	CPU_SH_NONE
diff --git a/include/asm-sh/push-switch.h b/include/asm-sh/push-switch.h
index dfc6bad..4903f9e 100644
--- a/include/asm-sh/push-switch.h
+++ b/include/asm-sh/push-switch.h
@@ -4,6 +4,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
+#include <linux/platform_device.h>
 
 struct push_switch {
 	/* switch state */
@@ -12,6 +13,8 @@
 	struct timer_list	debounce;
 	/* workqueue */
 	struct work_struct	work;
+	/* platform device, for workqueue handler */
+	struct platform_device	*pdev;
 };
 
 struct push_switch_platform_info {
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 952783d..3227bc9 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -189,6 +189,7 @@
 
 #define MSR_IA32_PERFCTR0      0xc1
 #define MSR_IA32_PERFCTR1      0xc2
+#define MSR_FSB_FREQ		0xcd
 
 #define MSR_MTRRcap		0x0fe
 #define MSR_IA32_BBL_CR_CTL        0x119
@@ -311,6 +312,9 @@
 #define MSR_IA32_PERF_STATUS		0x198
 #define MSR_IA32_PERF_CTL		0x199
 
+#define MSR_IA32_MPERF			0xE7
+#define MSR_IA32_APERF			0xE8
+
 #define MSR_IA32_THERM_CONTROL		0x19a
 #define MSR_IA32_THERM_INTERRUPT	0x19b
 #define MSR_IA32_THERM_STATUS		0x19c
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index e1c7286..ea330d7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -342,7 +342,6 @@
 
 struct bio_vec;
 typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *);
-typedef void (activity_fn) (void *data, int rw);
 typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
 typedef void (prepare_flush_fn) (request_queue_t *, struct request *);
 typedef void (softirq_done_fn)(struct request *);
@@ -384,7 +383,6 @@
 	prep_rq_fn		*prep_rq_fn;
 	unplug_fn		*unplug_fn;
 	merge_bvec_fn		*merge_bvec_fn;
-	activity_fn		*activity_fn;
 	issue_flush_fn		*issue_flush_fn;
 	prepare_flush_fn	*prepare_flush_fn;
 	softirq_done_fn		*softirq_done_fn;
@@ -411,8 +409,6 @@
 	 */
 	void			*queuedata;
 
-	void			*activity_data;
-
 	/*
 	 * queue needs bounce pages for pages above this limit
 	 */
@@ -677,7 +673,6 @@
 extern void __blk_stop_queue(request_queue_t *q);
 extern void blk_run_queue(request_queue_t *);
 extern void blk_start_queueing(request_queue_t *);
-extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
 extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long);
 extern int blk_rq_unmap_user(struct request *);
 extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 4ea39fe..7f008f6 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -172,6 +172,8 @@
 				   unsigned int relation);
 
 
+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);
 
@@ -204,6 +206,7 @@
 	unsigned int	(*get)	(unsigned int cpu);
 
 	/* optional */
+	unsigned int (*getavg)	(unsigned int cpu);
 	int	(*exit)		(struct cpufreq_policy *policy);
 	int	(*suspend)	(struct cpufreq_policy *policy, pm_message_t pmsg);
 	int	(*resume)	(struct cpufreq_policy *policy);
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index ed6cc89..1cb054b 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -176,20 +176,20 @@
 };
 
 /* DCCP features (RFC 4340 section 6.4) */
- enum {
- 	DCCPF_RESERVED = 0,
- 	DCCPF_CCID = 1,
+enum {
+	DCCPF_RESERVED = 0,
+	DCCPF_CCID = 1,
 	DCCPF_SHORT_SEQNOS = 2,		/* XXX: not yet implemented */
- 	DCCPF_SEQUENCE_WINDOW = 3,
+	DCCPF_SEQUENCE_WINDOW = 3,
 	DCCPF_ECN_INCAPABLE = 4,	/* XXX: not yet implemented */
- 	DCCPF_ACK_RATIO = 5,
- 	DCCPF_SEND_ACK_VECTOR = 6,
- 	DCCPF_SEND_NDP_COUNT = 7,
+	DCCPF_ACK_RATIO = 5,
+	DCCPF_SEND_ACK_VECTOR = 6,
+	DCCPF_SEND_NDP_COUNT = 7,
 	DCCPF_MIN_CSUM_COVER = 8,
 	DCCPF_DATA_CHECKSUM = 9,	/* XXX: not yet implemented */
- 	/* 10-127 reserved */
- 	DCCPF_MIN_CCID_SPECIFIC = 128,
- 	DCCPF_MAX_CCID_SPECIFIC = 255,
+	/* 10-127 reserved */
+	DCCPF_MIN_CCID_SPECIFIC = 128,
+	DCCPF_MAX_CCID_SPECIFIC = 255,
 };
 
 /* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
@@ -427,7 +427,7 @@
 };
 
 #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1)
-#define DCCP_SERVICE_CODE_IS_ABSENT 		 0
+#define DCCP_SERVICE_CODE_IS_ABSENT		0
 
 static inline int dccp_list_has_service(const struct dccp_service_list *sl,
 					const __be32 service)
@@ -436,7 +436,7 @@
 		u32 i = sl->dccpsl_nr;
 		while (i--)
 			if (sl->dccpsl_list[i] == service)
-				return 1; 
+				return 1;
 	}
 	return 0;
 }
@@ -511,7 +511,7 @@
 	__u8				dccps_hc_tx_insert_options:1;
 	struct timer_list		dccps_xmit_timer;
 };
- 
+
 static inline struct dccp_sock *dccp_sk(const struct sock *sk)
 {
 	return (struct dccp_sock *)sk;
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 3da29e2..abb64c4 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -19,6 +19,7 @@
 #define _FSL_DEVICE_H_
 
 #include <linux/types.h>
+#include <linux/phy.h>
 
 /*
  * Some conventions on how we handle peripherals on Freescale chips
diff --git a/include/linux/i2c-algo-bit.h b/include/linux/i2c-algo-bit.h
index c8f8df2..937da70 100644
--- a/include/linux/i2c-algo-bit.h
+++ b/include/linux/i2c-algo-bit.h
@@ -26,9 +26,9 @@
 
 /* --- Defines for bit-adapters ---------------------------------------	*/
 /*
- * This struct contains the hw-dependent functions of bit-style adapters to 
+ * This struct contains the hw-dependent functions of bit-style adapters to
  * manipulate the line states, and to init any hw-specific features. This is
- * only used if you have more than one hw-type of adapter running. 
+ * only used if you have more than one hw-type of adapter running.
  */
 struct i2c_algo_bit_data {
 	void *data;		/* private data for lowlevel routines */
@@ -44,6 +44,5 @@
 };
 
 int i2c_bit_add_bus(struct i2c_adapter *);
-int i2c_bit_del_bus(struct i2c_adapter *);
 
 #endif /* _LINUX_I2C_ALGO_BIT_H */
diff --git a/include/linux/i2c-algo-ite.h b/include/linux/i2c-algo-ite.h
deleted file mode 100644
index 0073fe9..0000000
--- a/include/linux/i2c-algo-ite.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/* i2c-algo-ite.h i2c driver algorithms for ITE IIC adapters                 */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-97 Simon G. Vogl
-                   1998-99 Hans Berglund
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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.                */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
-   Frodo Looijaard <frodol@dds.nl> */
-
-/* Modifications by MontaVista Software, 2001
-   Changes made to support the ITE IIC peripheral */
-
-
-#ifndef I2C_ALGO_ITE_H
-#define I2C_ALGO_ITE_H 1
-
-#include <linux/types.h>
-
-/* Example of a sequential read request:
-	struct i2c_iic_msg s_msg; 
-
-	s_msg.addr=device_address;
-	s_msg.len=length;
-	s_msg.buf=buffer;
-	s_msg.waddr=word_address;
-	ioctl(file,I2C_SREAD, &s_msg);
- */
-#define I2C_SREAD	0x780	/* SREAD ioctl command */
-
-struct i2c_iic_msg {
-	__u16 addr;	/* device address */
-	__u16 waddr;	/* word address */
-	short len;	/* msg length */
-	char *buf;	/* pointer to msg data */
-};
-
-#ifdef __KERNEL__
-struct i2c_adapter;
-
-struct i2c_algo_iic_data {
-	void *data;		/* private data for lolevel routines	*/
-	void (*setiic) (void *data, int ctl, int val);
-	int  (*getiic) (void *data, int ctl);
-	int  (*getown) (void *data);
-	int  (*getclock) (void *data);
-	void (*waitforpin) (void);     
-
-	/* local settings */
-	int udelay;
-	int mdelay;
-	int timeout;
-};
-
-int i2c_iic_add_bus(struct i2c_adapter *);
-int i2c_iic_del_bus(struct i2c_adapter *);
-#endif /* __KERNEL__ */
-#endif /* I2C_ALGO_ITE_H */
diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
index 226693e..fce47c0 100644
--- a/include/linux/i2c-algo-pca.h
+++ b/include/linux/i2c-algo-pca.h
@@ -10,6 +10,5 @@
 };
 
 int i2c_pca_add_bus(struct i2c_adapter *);
-int i2c_pca_del_bus(struct i2c_adapter *);
 
 #endif /* _LINUX_I2C_ALGO_PCA_H */
diff --git a/include/linux/i2c-algo-pcf.h b/include/linux/i2c-algo-pcf.h
index 9908f3f..994eb86 100644
--- a/include/linux/i2c-algo-pcf.h
+++ b/include/linux/i2c-algo-pcf.h
@@ -31,7 +31,7 @@
 	int  (*getpcf) (void *data, int ctl);
 	int  (*getown) (void *data);
 	int  (*getclock) (void *data);
-	void (*waitforpin) (void);     
+	void (*waitforpin) (void);
 
 	/* local settings */
 	int udelay;
@@ -39,6 +39,5 @@
 };
 
 int i2c_pcf_add_bus(struct i2c_adapter *);
-int i2c_pcf_del_bus(struct i2c_adapter *);
 
 #endif /* _LINUX_I2C_ALGO_PCF_H */
diff --git a/include/linux/i2c-algo-sgi.h b/include/linux/i2c-algo-sgi.h
index 4a0113d..3b77150 100644
--- a/include/linux/i2c-algo-sgi.h
+++ b/include/linux/i2c-algo-sgi.h
@@ -22,6 +22,5 @@
 };
 
 int i2c_sgi_add_bus(struct i2c_adapter *);
-int i2c_sgi_del_bus(struct i2c_adapter *);
 
 #endif /* I2C_ALGO_SGI_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 0f4cf34..7ae3c332 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
-/* 									     */
+/*									     */
 /* i2c-id.h - identifier values for i2c drivers and adapters		     */
-/* 									     */
+/*									     */
 /* ------------------------------------------------------------------------- */
 /*   Copyright (C) 1995-1999 Simon G. Vogl
 
@@ -40,10 +40,10 @@
 #define I2C_DRIVERID_SAA7120	11	/* video encoder		*/
 #define I2C_DRIVERID_SAA7121	12	/* video encoder		*/
 #define I2C_DRIVERID_SAA7185B	13	/* video encoder		*/
-#define I2C_DRIVERID_CH7003	14	/* digital pc to tv encoder 	*/
+#define I2C_DRIVERID_CH7003	14	/* digital pc to tv encoder	*/
 #define I2C_DRIVERID_PCF8574A	15	/* i2c expander - 8 bit in/out	*/
 #define I2C_DRIVERID_PCF8582C	16	/* eeprom			*/
-#define I2C_DRIVERID_AT24Cxx	17	/* eeprom 1/2/4/8/16 K 		*/
+#define I2C_DRIVERID_AT24Cxx	17	/* eeprom 1/2/4/8/16 K		*/
 #define I2C_DRIVERID_TEA6300	18	/* audio mixer			*/
 #define I2C_DRIVERID_BT829	19	/* pc to tv encoder		*/
 #define I2C_DRIVERID_TDA9850	20	/* audio mixer			*/
@@ -82,9 +82,8 @@
 #define I2C_DRIVERID_STM41T00	52	/* real time clock		*/
 #define I2C_DRIVERID_UDA1342	53	/* UDA1342 audio codec		*/
 #define I2C_DRIVERID_ADV7170	54	/* video encoder		*/
-#define I2C_DRIVERID_RADEON	55	/* I2C bus on Radeon boards	*/
 #define I2C_DRIVERID_MAX1617	56	/* temp sensor			*/
-#define I2C_DRIVERID_SAA7191	57	/* video encoder		*/
+#define I2C_DRIVERID_SAA7191	57	/* video decoder		*/
 #define I2C_DRIVERID_INDYCAM	58	/* SGI IndyCam			*/
 #define I2C_DRIVERID_BT832	59	/* CMOS camera video processor	*/
 #define I2C_DRIVERID_TDA9887	60	/* TDA988x IF-PLL demodulator	*/
@@ -132,7 +131,6 @@
 #define I2C_DRIVERID_ADM1021 1008
 #define I2C_DRIVERID_ADM9240 1009
 #define I2C_DRIVERID_LTC1710 1010
-#define I2C_DRIVERID_ICSPLL 1012
 #define I2C_DRIVERID_BT869 1013
 #define I2C_DRIVERID_MAXILIFE 1014
 #define I2C_DRIVERID_MATORB 1015
@@ -165,7 +163,7 @@
  * ---- Adapter types ----------------------------------------------------
  */
 
-/* --- Bit algorithm adapters 						*/
+/* --- Bit algorithm adapters						*/
 #define I2C_HW_B_LP		0x010000 /* Parallel port Philips style */
 #define I2C_HW_B_SER		0x010002 /* Serial line interface */
 #define I2C_HW_B_BT848		0x010005 /* BT848 video boards */
@@ -213,9 +211,6 @@
 /* --- MPC8xx PowerPC adapters						*/
 #define I2C_HW_MPC8XX_EPON	0x110000 /* Eponymous MPC8xx I2C adapter */
 
-/* --- ITE based algorithms						*/
-#define I2C_HW_I_IIC		0x080000 /* controller on the ITE */
-
 /* --- PowerPC on-chip adapters						*/
 #define I2C_HW_OCP		0x120000 /* IBM on-chip I2C adapter */
 
diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h
new file mode 100644
index 0000000..e6e9c81
--- /dev/null
+++ b/include/linux/i2c-pnx.h
@@ -0,0 +1,43 @@
+/*
+ * Header file for I2C support on PNX010x/4008.
+ *
+ * Author: Dennis Kovalev <dkovalev@ru.mvista.com>
+ *
+ * 2004-2006 (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 __I2C_PNX_H__
+#define __I2C_PNX_H__
+
+#include <asm/arch/i2c.h>
+
+struct i2c_pnx_mif {
+	int			ret;		/* Return value */
+	int			mode;		/* Interface mode */
+	struct completion	complete;	/* I/O completion */
+	struct timer_list	timer;		/* Timeout */
+	char *			buf;		/* Data buffer */
+	int			len;		/* Length of data buffer */
+};
+
+struct i2c_pnx_algo_data {
+	u32			base;
+	u32			ioaddr;
+	int			irq;
+	struct i2c_pnx_mif	mif;
+	int			last;
+};
+
+struct i2c_pnx_data {
+	int (*suspend) (struct platform_device *pdev, pm_message_t state);
+	int (*resume) (struct platform_device *pdev);
+	u32 (*calculate_input_freq) (struct platform_device *pdev);
+	int (*set_clock_run) (struct platform_device *pdev);
+	int (*set_clock_stop) (struct platform_device *pdev);
+	struct i2c_adapter *adapter;
+};
+
+#endif /* __I2C_PNX_H__ */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 9b5d047..71e50d3 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
-/* 									     */
+/*									     */
 /* i2c.h - definitions for the i2c-bus interface			     */
-/* 									     */
+/*									     */
 /* ------------------------------------------------------------------------- */
 /*   Copyright (C) 1995-2000 Simon G. Vogl
 
@@ -27,7 +27,7 @@
 #define _LINUX_I2C_H
 
 #include <linux/types.h>
-#ifdef __KERNEL__ 
+#ifdef __KERNEL__
 #include <linux/module.h>
 #include <linux/i2c-id.h>
 #include <linux/mod_devicetable.h>
@@ -53,8 +53,8 @@
 
 /*
  * The master routines are the ones normally used to transmit data to devices
- * on a bus (or read from them). Apart from two basic transfer functions to 
- * transmit one message at a time, a more complex version can be used to 
+ * on a bus (or read from them). Apart from two basic transfer functions to
+ * transmit one message at a time, a more complex version can be used to
  * transmit an arbitrary number of messages without interruption.
  */
 extern int i2c_master_send(struct i2c_client *,const char* ,int);
@@ -67,10 +67,10 @@
 
 /* This is the very generalized SMBus access routine. You probably do not
    want to use this, though; one of the functions below may be much easier,
-   and probably just as fast. 
+   and probably just as fast.
    Note that we use i2c_adapter here, because you do not need a specific
    smbus adapter to call this function. */
-extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr, 
+extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
                            unsigned short flags,
                            char read_write, u8 command, int size,
                            union i2c_smbus_data * data);
@@ -112,14 +112,14 @@
 
 	/* Notifies the driver that a new bus has appeared. This routine
 	 * can be used by the driver to test if the bus meets its conditions
-	 * & seek for the presence of the chip(s) it supports. If found, it 
+	 * & seek for the presence of the chip(s) it supports. If found, it
 	 * registers the client(s) that are on the bus to the i2c admin. via
 	 * i2c_attach_client.
 	 */
 	int (*attach_adapter)(struct i2c_adapter *);
 	int (*detach_adapter)(struct i2c_adapter *);
 
-	/* tells the driver that a client is about to be deleted & gives it 
+	/* tells the driver that a client is about to be deleted & gives it
 	 * the chance to remove its private data. Also, if the client struct
 	 * has been dynamically allocated by the driver in the function above,
 	 * it must be freed here.
@@ -139,13 +139,13 @@
 #define I2C_NAME_SIZE	50
 
 /*
- * i2c_client identifies a single device (i.e. chip) that is connected to an 
+ * i2c_client identifies a single device (i.e. chip) that is connected to an
  * i2c bus. The behaviour is defined by the routines of the driver. This
  * function is mainly used for lookup & other admin. functions.
  */
 struct i2c_client {
 	unsigned int flags;		/* div., see below		*/
-	unsigned short addr;		/* chip address - NOTE: 7bit 	*/
+	unsigned short addr;		/* chip address - NOTE: 7bit	*/
 					/* addresses are stored in the	*/
 					/* _LOWER_ 7 bits		*/
 	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
@@ -182,14 +182,14 @@
  */
 struct i2c_algorithm {
 	/* If an adapter algorithm can't do I2C-level access, set master_xfer
-	   to NULL. If an adapter algorithm can do SMBus access, set 
+	   to NULL. If an adapter algorithm can do SMBus access, set
 	   smbus_xfer. If set to NULL, the SMBus protocol is simulated
 	   using common I2C messages */
 	/* master_xfer should return the number of messages successfully
 	   processed, or a negative value on error */
-	int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs, 
+	int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,
 	                   int num);
-	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, 
+	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
 	                   unsigned short flags, char read_write,
 	                   u8 command, int size, union i2c_smbus_data * data);
 
@@ -216,6 +216,7 @@
 	int (*client_unregister)(struct i2c_client *);
 
 	/* data fields that are valid for all devices	*/
+	u8 level; 			/* nesting level for lockdep */
 	struct mutex bus_lock;
 	struct mutex clist_lock;
 
@@ -316,7 +317,7 @@
  * It will only call found_proc if some client is connected at the
  * specific address (unless a 'force' matched);
  */
-extern int i2c_probe(struct i2c_adapter *adapter, 
+extern int i2c_probe(struct i2c_adapter *adapter,
 		struct i2c_client_address_data *address_data,
 		int (*found_proc) (struct i2c_adapter *, int, int));
 
@@ -352,15 +353,15 @@
  */
 struct i2c_msg {
 	__u16 addr;	/* slave address			*/
- 	__u16 flags;		
+	__u16 flags;
 #define I2C_M_TEN	0x10	/* we have a ten bit chip address	*/
 #define I2C_M_RD	0x01
 #define I2C_M_NOSTART	0x4000
 #define I2C_M_REV_DIR_ADDR	0x2000
 #define I2C_M_IGNORE_NAK	0x1000
 #define I2C_M_NO_RD_ACK		0x0800
- 	__u16 len;		/* msg length				*/
- 	__u8 *buf;		/* pointer to msg data			*/
+	__u16 len;		/* msg length				*/
+	__u8 *buf;		/* pointer to msg data			*/
 };
 
 /* To determine what functionality is present */
@@ -370,16 +371,16 @@
 #define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
 #define I2C_FUNC_SMBUS_HWPEC_CALC	0x00000008 /* SMBus 2.0 */
 #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0x00008000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_QUICK		0x00010000 
-#define I2C_FUNC_SMBUS_READ_BYTE	0x00020000 
-#define I2C_FUNC_SMBUS_WRITE_BYTE	0x00040000 
-#define I2C_FUNC_SMBUS_READ_BYTE_DATA	0x00080000 
-#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA	0x00100000 
-#define I2C_FUNC_SMBUS_READ_WORD_DATA	0x00200000 
-#define I2C_FUNC_SMBUS_WRITE_WORD_DATA	0x00400000 
-#define I2C_FUNC_SMBUS_PROC_CALL	0x00800000 
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA	0x01000000 
-#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 
+#define I2C_FUNC_SMBUS_QUICK		0x00010000
+#define I2C_FUNC_SMBUS_READ_BYTE	0x00020000
+#define I2C_FUNC_SMBUS_WRITE_BYTE	0x00040000
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA	0x00080000
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA	0x00100000
+#define I2C_FUNC_SMBUS_READ_WORD_DATA	0x00200000
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA	0x00400000
+#define I2C_FUNC_SMBUS_PROC_CALL	0x00800000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA	0x01000000
+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
 #define I2C_FUNC_SMBUS_READ_I2C_BLOCK	0x04000000 /* I2C-like block xfer  */
 #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK	0x08000000 /* w/ 1-byte reg. addr. */
 #define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2	 0x10000000 /* I2C-like block xfer  */
@@ -406,10 +407,10 @@
                              I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
                              I2C_FUNC_SMBUS_I2C_BLOCK)
 
-/* 
- * Data for SMBus Messages 
+/*
+ * Data for SMBus Messages
  */
-#define I2C_SMBUS_BLOCK_MAX	32	/* As specified in SMBus standard */	
+#define I2C_SMBUS_BLOCK_MAX	32	/* As specified in SMBus standard */
 union i2c_smbus_data {
 	__u8 byte;
 	__u16 word;
@@ -421,11 +422,11 @@
 #define I2C_SMBUS_READ	1
 #define I2C_SMBUS_WRITE	0
 
-/* SMBus transaction types (size parameter in the above functions) 
+/* SMBus transaction types (size parameter in the above functions)
    Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
 #define I2C_SMBUS_QUICK		    0
 #define I2C_SMBUS_BYTE		    1
-#define I2C_SMBUS_BYTE_DATA	    2 
+#define I2C_SMBUS_BYTE_DATA	    2
 #define I2C_SMBUS_WORD_DATA	    3
 #define I2C_SMBUS_PROC_CALL	    4
 #define I2C_SMBUS_BLOCK_DATA	    5
@@ -434,15 +435,15 @@
 
 
 /* ----- commands for the ioctl like i2c_command call:
- * note that additional calls are defined in the algorithm and hw 
- *	dependent layers - these can be listed here, or see the 
+ * note that additional calls are defined in the algorithm and hw
+ *	dependent layers - these can be listed here, or see the
  *	corresponding header files.
  */
 				/* -> bit-adapter specific ioctls	*/
 #define I2C_RETRIES	0x0701	/* number of times a device address      */
 				/* should be polled when not            */
-                                /* acknowledging 			*/
-#define I2C_TIMEOUT	0x0702	/* set timeout - call with int 		*/
+                                /* acknowledging			*/
+#define I2C_TIMEOUT	0x0702	/* set timeout - call with int		*/
 
 
 /* this is for i2c-dev.c	*/
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 64e070f6..e26a039 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -804,8 +804,6 @@
 	void		*hwif_data;	/* extra hwif data */
 
 	unsigned dma;
-
-	void (*led_act)(void *data, int rw);
 } ____cacheline_internodealigned_in_smp ide_hwif_t;
 
 /*
diff --git a/include/linux/init.h b/include/linux/init.h
index 5eb5d24..5a593a1 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -111,6 +111,7 @@
 #define subsys_initcall_sync(fn)	__define_initcall("4s",fn,4s)
 #define fs_initcall(fn)			__define_initcall("5",fn,5)
 #define fs_initcall_sync(fn)		__define_initcall("5s",fn,5s)
+#define rootfs_initcall(fn)		__define_initcall("rootfs",fn,rootfs)
 #define device_initcall(fn)		__define_initcall("6",fn,6)
 #define device_initcall_sync(fn)	__define_initcall("6s",fn,6s)
 #define late_initcall(fn)		__define_initcall("7",fn,7)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e8bfac3..b0c4a05 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -17,8 +17,6 @@
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
-extern const char linux_banner[];
-
 #define INT_MAX		((int)(~0U>>1))
 #define INT_MIN		(-INT_MAX - 1)
 #define UINT_MAX	(~0U)
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 4600093..6b0648c 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -44,8 +44,11 @@
 #define SEQLOCK_UNLOCKED \
 		 __SEQLOCK_UNLOCKED(old_style_seqlock_init)
 
-#define seqlock_init(x) \
-		do { *(x) = (seqlock_t) __SEQLOCK_UNLOCKED(x); } while (0)
+#define seqlock_init(x)					\
+	do {						\
+		(x)->sequence = 0;			\
+		spin_lock_init(&(x)->lock);		\
+	} while (0)
 
 #define DEFINE_SEQLOCK(x) \
 		seqlock_t x = __SEQLOCK_UNLOCKED(x)
diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h
index 31a9b25..8a8462b 100644
--- a/include/linux/tfrc.h
+++ b/include/linux/tfrc.h
@@ -37,10 +37,14 @@
  * 	@tfrctx_p:	current loss event rate (5.4)
  * 	@tfrctx_rto:	estimate of RTO, equals 4*RTT (4.3)
  * 	@tfrctx_ipi:	inter-packet interval (4.6)
+ *
+ *  Note: X and X_recv are both maintained in units of 64 * bytes/second. This
+ *        enables a finer resolution of sending rates and avoids problems with
+ *        integer arithmetic; u32 is not sufficient as scaling consumes 6 bits.
  */
 struct tfrc_tx_info {
-	__u32 tfrctx_x;
-	__u32 tfrctx_x_recv;
+	__u64 tfrctx_x;
+	__u64 tfrctx_x_recv;
 	__u32 tfrctx_x_calc;
 	__u32 tfrctx_rtt;
 	__u32 tfrctx_p;
diff --git a/include/net/ax25.h b/include/net/ax25.h
index e1d116f..14b72d8 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -285,6 +285,8 @@
 extern const ax25_address ax25_bcast;
 extern const ax25_address ax25_defaddr;
 extern const ax25_address null_ax25_address;
+extern char *ax2asc(char *buf, const ax25_address *);
+extern void asc2ax(ax25_address *addr, const char *callsign);
 extern int ax25cmp(const ax25_address *, const ax25_address *);
 extern int ax25digicmp(const ax25_digi *, const ax25_digi *);
 extern const unsigned char *ax25_addr_parse(const unsigned char *, int,
diff --git a/init/initramfs.c b/init/initramfs.c
index 85f0403..4fa0f797 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -526,7 +526,7 @@
 
 #endif
 
-void __init populate_rootfs(void)
+static int __init populate_rootfs(void)
 {
 	char *err = unpack_to_rootfs(__initramfs_start,
 			 __initramfs_end - __initramfs_start, 0);
@@ -544,7 +544,7 @@
 			unpack_to_rootfs((char *)initrd_start,
 				initrd_end - initrd_start, 0);
 			free_initrd();
-			return;
+			return 0;
 		}
 		printk("it isn't (%s); looks like an initrd\n", err);
 		fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
@@ -565,4 +565,6 @@
 #endif
 	}
 #endif
+	return 0;
 }
+rootfs_initcall(populate_rootfs);
diff --git a/init/main.c b/init/main.c
index 036f97c..e3f0bb2 100644
--- a/init/main.c
+++ b/init/main.c
@@ -94,7 +94,6 @@
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
 extern void free_initmem(void);
-extern void populate_rootfs(void);
 extern void driver_init(void);
 extern void prepare_namespace(void);
 #ifdef	CONFIG_ACPI
@@ -483,6 +482,12 @@
 {
 }
 
+static const char linux_banner[] =
+	"Linux version " UTS_RELEASE
+	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+	" (" LINUX_COMPILER ")"
+	" " UTS_VERSION "\n";
+
 asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
@@ -509,7 +514,7 @@
 	boot_cpu_init();
 	page_address_init();
 	printk(KERN_NOTICE);
-	printk(linux_banner, UTS_RELEASE, UTS_VERSION);
+	printk(linux_banner);
 	setup_arch(&command_line);
 	unwind_setup();
 	setup_per_cpu_areas();
@@ -739,12 +744,6 @@
 
 	cpuset_init_smp();
 
-	/*
-	 * Do this before initcalls, because some drivers want to access
-	 * firmware files.
-	 */
-	populate_rootfs();
-
 	do_basic_setup();
 
 	/*
diff --git a/init/version.c b/init/version.c
index 2a5dfcd..9d96d36 100644
--- a/init/version.c
+++ b/init/version.c
@@ -33,8 +33,3 @@
 	},
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
-
-const char linux_banner[] =
-	"Linux version %s (" LINUX_COMPILE_BY "@"
-	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") %s\n";
-
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 21a0616..97a49c7 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -83,7 +83,7 @@
  */
 void asc2ax(ax25_address *addr, const char *callsign)
 {
-	char *s;
+	const char *s;
 	int n;
 
 	for (s = callsign, n = 0; n < 6; n++) {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 8a27128..823215d 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -55,6 +55,7 @@
 	struct netpoll_info *npinfo =
 		container_of(work, struct netpoll_info, tx_work.work);
 	struct sk_buff *skb;
+	unsigned long flags;
 
 	while ((skb = skb_dequeue(&npinfo->txq))) {
 		struct net_device *dev = skb->dev;
@@ -64,15 +65,19 @@
 			continue;
 		}
 
-		netif_tx_lock_bh(dev);
+		local_irq_save(flags);
+		netif_tx_lock(dev);
 		if (netif_queue_stopped(dev) ||
 		    dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
 			skb_queue_head(&npinfo->txq, skb);
-			netif_tx_unlock_bh(dev);
+			netif_tx_unlock(dev);
+			local_irq_restore(flags);
 
 			schedule_delayed_work(&npinfo->tx_work, HZ/10);
 			return;
 		}
+		netif_tx_unlock(dev);
+		local_irq_restore(flags);
 	}
 }
 
@@ -242,22 +247,28 @@
 
 	/* don't get messages out of order, and no recursion */
 	if (skb_queue_len(&npinfo->txq) == 0 &&
-	    npinfo->poll_owner != smp_processor_id() &&
-	    netif_tx_trylock(dev)) {
-		/* try until next clock tick */
-		for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) {
-			if (!netif_queue_stopped(dev))
-				status = dev->hard_start_xmit(skb, dev);
+		    npinfo->poll_owner != smp_processor_id()) {
+		unsigned long flags;
 
-			if (status == NETDEV_TX_OK)
-				break;
+		local_irq_save(flags);
+		if (netif_tx_trylock(dev)) {
+			/* try until next clock tick */
+			for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+					tries > 0; --tries) {
+				if (!netif_queue_stopped(dev))
+					status = dev->hard_start_xmit(skb, dev);
 
-			/* tickle device maybe there is some cleanup */
-			netpoll_poll(np);
+				if (status == NETDEV_TX_OK)
+					break;
 
-			udelay(USEC_PER_POLL);
+				/* tickle device maybe there is some cleanup */
+				netpoll_poll(np);
+
+				udelay(USEC_PER_POLL);
+			}
+			netif_tx_unlock(dev);
 		}
-		netif_tx_unlock(dev);
+		local_irq_restore(flags);
 	}
 
 	if (status != NETDEV_TX_OK) {
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 1f4727d..a086c63 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -223,7 +223,7 @@
 			gap = -new_head;
 		}
 		new_head += DCCP_MAX_ACKVEC_LEN;
-	} 
+	}
 
 	av->dccpav_buf_head = new_head;
 
@@ -336,7 +336,7 @@
 void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
 {
 	dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len,
-			 		(unsigned long long)ackno);
+			 (unsigned long long)ackno);
 
 	while (len--) {
 		const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index bcc2d12..c65cb24 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -43,8 +43,6 @@
 						    unsigned char* value);
 	int		(*ccid_hc_rx_insert_options)(struct sock *sk,
 						     struct sk_buff *skb);
-	int		(*ccid_hc_tx_insert_options)(struct sock *sk,
-						     struct sk_buff *skb);
 	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
 						  struct sk_buff *skb);
 	int		(*ccid_hc_tx_parse_options)(struct sock *sk,
@@ -146,14 +144,6 @@
 	return rc;
 }
 
-static inline int ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
-					    struct sk_buff *skb)
-{
-	if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
-		return ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb);
-	return 0;
-}
-
 static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
 					    struct sk_buff *skb)
 {
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 2555be8..fd38b05 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -351,7 +351,7 @@
 
 		while (seqp != hctx->ccid2hctx_seqh) {
 			ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
-			       	       (unsigned long long)seqp->ccid2s_seq,
+				       (unsigned long long)seqp->ccid2s_seq,
 				       seqp->ccid2s_acked, seqp->ccid2s_sent);
 			seqp = seqp->ccid2s_next;
 		}
@@ -473,7 +473,7 @@
 		/* first measurement */
 		if (hctx->ccid2hctx_srtt == -1) {
 			ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
-			       	       r, jiffies,
+				       r, jiffies,
 				       (unsigned long long)seqp->ccid2s_seq);
 			ccid2_change_srtt(hctx, r);
 			hctx->ccid2hctx_rttvar = r >> 1;
@@ -518,8 +518,8 @@
 		hctx->ccid2hctx_lastrtt = jiffies;
 
 		ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
-		       	       hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
-		       	       hctx->ccid2hctx_rto, HZ, r);
+			       hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
+			       hctx->ccid2hctx_rto, HZ, r);
 		hctx->ccid2hctx_sent = 0;
 	}
 
@@ -667,9 +667,9 @@
 				/* new packet received or marked */
 				if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
 				    !seqp->ccid2s_acked) {
-				    	if (state ==
+					if (state ==
 					    DCCP_ACKVEC_STATE_ECN_MARKED) {
-					    	ccid2_congestion_event(hctx,
+						ccid2_congestion_event(hctx,
 								       seqp);
 					} else
 						ccid2_new_ack(sk, seqp,
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 66a27b9..fa6b753 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -41,27 +41,6 @@
 #include "lib/tfrc.h"
 #include "ccid3.h"
 
-/*
- * Reason for maths here is to avoid 32 bit overflow when a is big.
- * With this we get close to the limit.
- */
-static u32 usecs_div(const u32 a, const u32 b)
-{
-	const u32 div = a < (UINT_MAX / (USEC_PER_SEC /    10)) ?    10 :
-			a < (UINT_MAX / (USEC_PER_SEC /    50)) ?    50 :
-			a < (UINT_MAX / (USEC_PER_SEC /   100)) ?   100 :
-			a < (UINT_MAX / (USEC_PER_SEC /   500)) ?   500 :
-			a < (UINT_MAX / (USEC_PER_SEC /  1000)) ?  1000 :
-			a < (UINT_MAX / (USEC_PER_SEC /  5000)) ?  5000 :
-			a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
-			a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
-								 100000;
-	const u32 tmp = a * (USEC_PER_SEC / div);
-	return (b >= 2 * div) ? tmp / (b / div) : tmp;
-}
-
-
-
 #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
 static int ccid3_debug;
 #define ccid3_pr_debug(format, a...)	DCCP_PR_DEBUG(ccid3_debug, format, ##a)
@@ -108,8 +87,9 @@
 {
 	timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
 
-	/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
-	hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x);
+	/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
+	hctx->ccid3hctx_t_ipi = scaled_div(hctx->ccid3hctx_s,
+					   hctx->ccid3hctx_x >> 6);
 
 	/* Update nominal send time with regard to the new t_ipi */
 	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
@@ -128,40 +108,44 @@
  *          X = max(min(2 * X, 2 * X_recv), s / R);
  *          tld = now;
  *
+ * Note: X and X_recv are both stored in units of 64 * bytes/second, to support
+ *       fine-grained resolution of sending rates. This requires scaling by 2^6
+ *       throughout the code. Only X_calc is unscaled (in bytes/second).
+ *
  * If X has changed, we also update the scheduled send time t_now,
  * the inter-packet interval t_ipi, and the delta value.
- */ 
+ */
 static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
 
 {
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-	const __u32 old_x = hctx->ccid3hctx_x;
+	const  __u64 old_x = hctx->ccid3hctx_x;
 
 	if (hctx->ccid3hctx_p > 0) {
-		hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
-						     hctx->ccid3hctx_rtt,
-						     hctx->ccid3hctx_p);
-		hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc,
-						   hctx->ccid3hctx_x_recv * 2),
-					       hctx->ccid3hctx_s / TFRC_T_MBI);
 
-	} else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >=
-							  hctx->ccid3hctx_rtt) {
-		hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv,
-					    hctx->ccid3hctx_x      ) * 2,
-					usecs_div(hctx->ccid3hctx_s,
-					       	  hctx->ccid3hctx_rtt)   );
+		hctx->ccid3hctx_x = min(((__u64)hctx->ccid3hctx_x_calc) << 6,
+					hctx->ccid3hctx_x_recv * 2);
+		hctx->ccid3hctx_x = max(hctx->ccid3hctx_x,
+					(((__u64)hctx->ccid3hctx_s) << 6) /
+								TFRC_T_MBI);
+
+	} else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) -
+			(suseconds_t)hctx->ccid3hctx_rtt >= 0) {
+
+		hctx->ccid3hctx_x =
+			max(2 * min(hctx->ccid3hctx_x, hctx->ccid3hctx_x_recv),
+			    scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
+				       hctx->ccid3hctx_rtt));
 		hctx->ccid3hctx_t_ld = *now;
-	} else
-		ccid3_pr_debug("Not changing X\n");
+	}
 
 	if (hctx->ccid3hctx_x != old_x)
 		ccid3_update_send_time(hctx);
 }
 
 /*
- * 	Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
- * 	@len: DCCP packet payload size in bytes
+ *	Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
+ *	@len: DCCP packet payload size in bytes
  */
 static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
 {
@@ -178,6 +162,33 @@
 	 */
 }
 
+/*
+ *	Update Window Counter using the algorithm from [RFC 4342, 8.1].
+ *	The algorithm is not applicable if RTT < 4 microseconds.
+ */
+static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
+						struct timeval *now)
+{
+	suseconds_t delta;
+	u32 quarter_rtts;
+
+	if (unlikely(hctx->ccid3hctx_rtt < 4))	/* avoid divide-by-zero */
+		return;
+
+	delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
+	DCCP_BUG_ON(delta < 0);
+
+	quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+
+	if (quarter_rtts > 0) {
+		hctx->ccid3hctx_t_last_win_count = *now;
+		hctx->ccid3hctx_last_win_count	+= min_t(u32, quarter_rtts, 5);
+		hctx->ccid3hctx_last_win_count	&= 0xF;		/* mod 16 */
+
+		ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
+	}
+}
+
 static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
 {
 	struct sock *sk = (struct sock *)data;
@@ -191,20 +202,20 @@
 		goto restart_timer;
 	}
 
-	ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
+	ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk,
 		       ccid3_tx_state_name(hctx->ccid3hctx_state));
-	
+
 	switch (hctx->ccid3hctx_state) {
 	case TFRC_SSTATE_NO_FBACK:
 		/* RFC 3448, 4.4: Halve send rate directly */
-		hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2,
-					       hctx->ccid3hctx_s / TFRC_T_MBI);
+		hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2,
+					(((__u64)hctx->ccid3hctx_s) << 6) /
+								    TFRC_T_MBI);
 
-		ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
-			       "bytes/s\n",
-			       dccp_role(sk), sk,
+		ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u "
+			       "bytes/s\n", dccp_role(sk), sk,
 			       ccid3_tx_state_name(hctx->ccid3hctx_state),
-			       hctx->ccid3hctx_x);
+			       (unsigned)(hctx->ccid3hctx_x >> 6));
 		/* The value of R is still undefined and so we can not recompute
 		 * the timout value. Keep initial value as per [RFC 4342, 5]. */
 		t_nfb = TFRC_INITIAL_TIMEOUT;
@@ -213,34 +224,46 @@
 	case TFRC_SSTATE_FBACK:
 		/*
 		 * Check if IDLE since last timeout and recv rate is less than
-		 * 4 packets per RTT
+		 * 4 packets (in units of 64*bytes/sec) per RTT
 		 */
 		if (!hctx->ccid3hctx_idle ||
-		    (hctx->ccid3hctx_x_recv >=
-		     4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
+		    (hctx->ccid3hctx_x_recv >= 4 *
+		     scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
+				hctx->ccid3hctx_rtt))) {
 			struct timeval now;
 
-			ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
+			ccid3_pr_debug("%s(%p, state=%s), not idle\n",
 				       dccp_role(sk), sk,
-				       ccid3_tx_state_name(hctx->ccid3hctx_state));
-			/* Halve sending rate */
+				   ccid3_tx_state_name(hctx->ccid3hctx_state));
 
-			/*  If (p == 0 || X_calc > 2 * X_recv)
+			/*
+			 *  Modify the cached value of X_recv [RFC 3448, 4.4]
+			 *
+			 *  If (p == 0 || X_calc > 2 * X_recv)
 			 *    X_recv = max(X_recv / 2, s / (2 * t_mbi));
 			 *  Else
 			 *    X_recv = X_calc / 4;
+			 *
+			 *  Note that X_recv is scaled by 2^6 while X_calc is not
 			 */
 			BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);
 
 			if (hctx->ccid3hctx_p  == 0 ||
-			    hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
-				hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
-								    hctx->ccid3hctx_s / (2 * TFRC_T_MBI));
-			else
-				hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
+			    (hctx->ccid3hctx_x_calc >
+			     (hctx->ccid3hctx_x_recv >> 5))) {
 
-			/* Update sending rate */
-			dccp_timestamp(sk, &now);
+				hctx->ccid3hctx_x_recv =
+					max(hctx->ccid3hctx_x_recv / 2,
+					    (((__u64)hctx->ccid3hctx_s) << 6) /
+							  (2 * TFRC_T_MBI));
+
+				if (hctx->ccid3hctx_p == 0)
+					dccp_timestamp(sk, &now);
+			} else {
+				hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;
+				hctx->ccid3hctx_x_recv <<= 4;
+			}
+			/* Now recalculate X [RFC 3448, 4.3, step (4)] */
 			ccid3_hc_tx_update_x(sk, &now);
 		}
 		/*
@@ -251,7 +274,7 @@
 		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
 		break;
 	case TFRC_SSTATE_NO_SENT:
-		DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk);
+		DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk);
 		/* fall through */
 	case TFRC_SSTATE_TERM:
 		goto out;
@@ -277,9 +300,8 @@
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-	struct dccp_tx_hist_entry *new_packet;
 	struct timeval now;
-	long delay;
+	suseconds_t delay;
 
 	BUG_ON(hctx == NULL);
 
@@ -291,34 +313,21 @@
 	if (unlikely(skb->len == 0))
 		return -EBADMSG;
 
-	/* See if last packet allocated was not sent */
-	new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
-	if (new_packet == NULL || new_packet->dccphtx_sent) {
-		new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
-						    GFP_ATOMIC);
-
-		if (unlikely(new_packet == NULL)) {
-			DCCP_WARN("%s, sk=%p, not enough mem to add to history,"
-				  "send refused\n", dccp_role(sk), sk);
-			return -ENOBUFS;
-		}
-
-		dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
-	}
-
 	dccp_timestamp(sk, &now);
 
 	switch (hctx->ccid3hctx_state) {
 	case TFRC_SSTATE_NO_SENT:
 		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
-			       jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
+			       (jiffies +
+			        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);
 
-		/* Set initial sending rate to 1 packet per second */
+		/* Set initial sending rate X/s to 1pps (X is scaled by 2^6) */
 		ccid3_hc_tx_update_s(hctx, skb->len);
-		hctx->ccid3hctx_x     = hctx->ccid3hctx_s;
+		hctx->ccid3hctx_x = hctx->ccid3hctx_s;
+		hctx->ccid3hctx_x <<= 6;
 
 		/* First timeout, according to [RFC 3448, 4.2], is 1 second */
 		hctx->ccid3hctx_t_ipi = USEC_PER_SEC;
@@ -332,77 +341,57 @@
 	case TFRC_SSTATE_FBACK:
 		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
 		/*
-		 * 	Scheduling of packet transmissions [RFC 3448, 4.6]
+		 *	Scheduling of packet transmissions [RFC 3448, 4.6]
 		 *
 		 * if (t_now > t_nom - delta)
 		 *       // send the packet now
 		 * else
 		 *       // send the packet in (t_nom - t_now) milliseconds.
 		 */
-		if (delay - (long)hctx->ccid3hctx_delta >= 0)
+		if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
 			return delay / 1000L;
+
+		ccid3_hc_tx_update_win_count(hctx, &now);
 		break;
 	case TFRC_SSTATE_TERM:
-		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
 		return -EINVAL;
 	}
 
 	/* prepare to send now (add options etc.) */
 	dp->dccps_hc_tx_insert_options = 1;
-	new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval =
-				    hctx->ccid3hctx_last_win_count;
+	DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
+
+	/* set the nominal send time for the next following packet */
 	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
 
 	return 0;
 }
 
-static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
+static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
+				    unsigned int len)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	struct timeval now;
-	unsigned long quarter_rtt;
 	struct dccp_tx_hist_entry *packet;
 
 	BUG_ON(hctx == NULL);
 
-	dccp_timestamp(sk, &now);
-
 	ccid3_hc_tx_update_s(hctx, len);
 
-	packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+	packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
 	if (unlikely(packet == NULL)) {
-		DCCP_WARN("packet doesn't exist in history!\n");
+		DCCP_CRIT("packet history - out of memory!");
 		return;
 	}
-	if (unlikely(packet->dccphtx_sent)) {
-		DCCP_WARN("no unsent packet in history!\n");
-		return;
-	}
+	dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);
+
+	dccp_timestamp(sk, &now);
 	packet->dccphtx_tstamp = now;
-	packet->dccphtx_seqno  = dp->dccps_gss;
-	/*
-	 * Check if win_count have changed
-	 * Algorithm in "8.1. Window Counter Value" in RFC 4342.
-	 */
-	quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
-	if (likely(hctx->ccid3hctx_rtt > 8))
-		quarter_rtt /= hctx->ccid3hctx_rtt / 4;
-
-	if (quarter_rtt > 0) {
-		hctx->ccid3hctx_t_last_win_count = now;
-		hctx->ccid3hctx_last_win_count	 = (hctx->ccid3hctx_last_win_count +
-						    min_t(unsigned long, quarter_rtt, 5)) % 16;
-		ccid3_pr_debug("%s, sk=%p, window changed from "
-			       "%u to %u!\n",
-			       dccp_role(sk), sk,
-			       packet->dccphtx_ccval,
-			       hctx->ccid3hctx_last_win_count);
-	}
-
-	hctx->ccid3hctx_idle = 0;
-	packet->dccphtx_rtt  = hctx->ccid3hctx_rtt;
-	packet->dccphtx_sent = 1;
+	packet->dccphtx_seqno  = dccp_sk(sk)->dccps_gss;
+	packet->dccphtx_rtt    = hctx->ccid3hctx_rtt;
+	packet->dccphtx_sent   = 1;
+	hctx->ccid3hctx_idle   = 0;
 }
 
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -414,7 +403,7 @@
 	struct timeval now;
 	unsigned long t_nfb;
 	u32 pinv;
-	long r_sample, t_elapsed;
+	suseconds_t r_sample, t_elapsed;
 
 	BUG_ON(hctx == NULL);
 
@@ -430,44 +419,44 @@
 	case TFRC_SSTATE_FBACK:
 		/* get packet from history to look up t_recvdata */
 		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
-						 DCCP_SKB_CB(skb)->dccpd_ack_seq);
+					      DCCP_SKB_CB(skb)->dccpd_ack_seq);
 		if (unlikely(packet == NULL)) {
 			DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist "
 				  "in history!\n",  dccp_role(sk), sk,
 			    (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
-				  dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+				dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
 			return;
 		}
 
-		/* Update receive rate */
+		/* Update receive rate in units of 64 * bytes/second */
 		hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;
+		hctx->ccid3hctx_x_recv <<= 6;
 
 		/* Update loss event rate */
 		pinv = opt_recv->ccid3or_loss_event_rate;
-		if (pinv == ~0U || pinv == 0)
+		if (pinv == ~0U || pinv == 0)	       /* see RFC 4342, 8.5   */
 			hctx->ccid3hctx_p = 0;
-		else
- 			hctx->ccid3hctx_p = 1000000 / pinv;
+		else				       /* can not exceed 100% */
+			hctx->ccid3hctx_p = 1000000 / pinv;
 
 		dccp_timestamp(sk, &now);
 
 		/*
 		 * Calculate new round trip sample as per [RFC 3448, 4.3] by
-		 * 	R_sample  =  (now - t_recvdata) - t_elapsed
+		 *	R_sample  =  (now - t_recvdata) - t_elapsed
 		 */
 		r_sample  = timeval_delta(&now, &packet->dccphtx_tstamp);
 		t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
 
-		if (unlikely(r_sample <= 0)) {
-			DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample);
-			r_sample = 0;
-		} else if (unlikely(r_sample <= t_elapsed))
-			DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n",
-				  r_sample, t_elapsed);
+		DCCP_BUG_ON(r_sample < 0);
+		if (unlikely(r_sample <= t_elapsed))
+			DCCP_WARN("WARNING: r_sample=%dus <= t_elapsed=%dus\n",
+				  (int)r_sample, (int)t_elapsed);
 		else
 			r_sample -= t_elapsed;
+		CCID3_RTT_SANITY_CHECK(r_sample);
 
-		/* Update RTT estimate by 
+		/* Update RTT estimate by
 		 * If (No feedback recv)
 		 *    R = R_sample;
 		 * Else
@@ -476,34 +465,45 @@
 		 * q is a constant, RFC 3448 recomments 0.9
 		 */
 		if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
-			/* Use Larger Initial Windows [RFC 4342, sec. 5]
-			 * We deviate in that we use `s' instead of `MSS'. */
-			u16 w_init = max(    4 * hctx->ccid3hctx_s,
-					 max(2 * hctx->ccid3hctx_s, 4380));
+			/*
+			 * Larger Initial Windows [RFC 4342, sec. 5]
+			 * We deviate in that we use `s' instead of `MSS'.
+			 */
+			__u64 w_init = min(4 * hctx->ccid3hctx_s,
+					   max(2 * hctx->ccid3hctx_s, 4380));
 			hctx->ccid3hctx_rtt  = r_sample;
-			hctx->ccid3hctx_x    = usecs_div(w_init, r_sample);
+			hctx->ccid3hctx_x    = scaled_div(w_init << 6, r_sample);
 			hctx->ccid3hctx_t_ld = now;
 
 			ccid3_update_send_time(hctx);
 
-			ccid3_pr_debug("%s(%p), s=%u, w_init=%u, "
-				       "R_sample=%ldus, X=%u\n", dccp_role(sk),
-				       sk, hctx->ccid3hctx_s, w_init, r_sample,
-				       hctx->ccid3hctx_x);
+			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,
+				       (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)
+				hctx->ccid3hctx_x_calc =
+					tfrc_calc_x(hctx->ccid3hctx_s,
+						    hctx->ccid3hctx_rtt,
+						    hctx->ccid3hctx_p);
 			ccid3_hc_tx_update_x(sk, &now);
 
-			ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, "
-				       "p=%u, X_calc=%u, X=%u\n", dccp_role(sk),
-				       sk, hctx->ccid3hctx_rtt, r_sample,
+			ccid3_pr_debug("%s(%p), RTT=%uus (sample=%dus), s=%u, "
+				       "p=%u, X_calc=%u, X_recv=%u, X=%u\n",
+				       dccp_role(sk),
+				       sk, hctx->ccid3hctx_rtt, (int)r_sample,
 				       hctx->ccid3hctx_s, hctx->ccid3hctx_p,
 				       hctx->ccid3hctx_x_calc,
-				       hctx->ccid3hctx_x);
+				       (unsigned)(hctx->ccid3hctx_x_recv >> 6),
+				       (unsigned)(hctx->ccid3hctx_x >> 6));
 		}
 
 		/* unschedule no feedback timer */
@@ -513,57 +513,48 @@
 		dccp_tx_hist_purge_older(ccid3_tx_hist,
 					 &hctx->ccid3hctx_hist, packet);
 		/*
-		 * As we have calculated new ipi, delta, t_nom it is possible that
-		 * we now can send a packet, so wake up dccp_wait_for_ccid
+		 * As we have calculated new ipi, delta, t_nom it is possible
+		 * that we now can send a packet, so wake up dccp_wait_for_ccid
 		 */
 		sk->sk_write_space(sk);
 
 		/*
 		 * Update timeout interval for the nofeedback timer.
 		 * We use a configuration option to increase the lower bound.
-		 * This can help avoid triggering the nofeedback timer too often
-		 * ('spinning') on LANs with small RTTs.
+		 * This can help avoid triggering the nofeedback timer too
+		 * often ('spinning') on LANs with small RTTs.
 		 */
 		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
 						   CONFIG_IP_DCCP_CCID3_RTO *
-						   (USEC_PER_SEC/1000)	     );
+						   (USEC_PER_SEC/1000));
 		/*
 		 * Schedule no feedback timer to expire in
 		 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
 		 */
 		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
-			
-		ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
-			       "expire in %lu jiffies (%luus)\n",
-			       dccp_role(sk), sk,
-			       usecs_to_jiffies(t_nfb), t_nfb);
 
-		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 
+		ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "
+			       "expire in %lu jiffies (%luus)\n",
+			       dccp_role(sk),
+			       sk, usecs_to_jiffies(t_nfb), t_nfb);
+
+		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
 				   jiffies + usecs_to_jiffies(t_nfb));
 
 		/* set idle flag */
-		hctx->ccid3hctx_idle = 1;   
+		hctx->ccid3hctx_idle = 1;
 		break;
 	case TFRC_SSTATE_NO_SENT:
-		if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT)
-			DCCP_WARN("Illegal ACK received - no packet sent\n");
+		/*
+		 * XXX when implementing bidirectional rx/tx check this again
+		 */
+		DCCP_WARN("Illegal ACK received - no packet sent\n");
 		/* fall through */
 	case TFRC_SSTATE_TERM:		/* ignore feedback when closing */
 		break;
 	}
 }
 
-static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
-{
-	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-
-	BUG_ON(hctx == NULL);
-
-	if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
-		DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
-	return 0;
-}
-
 static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
 				     unsigned char len, u16 idx,
 				     unsigned char *value)
@@ -588,13 +579,14 @@
 	switch (option) {
 	case TFRC_OPT_LOSS_EVENT_RATE:
 		if (unlikely(len != 4)) {
-			DCCP_WARN("%s, sk=%p, invalid len %d "
+			DCCP_WARN("%s(%p), invalid len %d "
 				  "for TFRC_OPT_LOSS_EVENT_RATE\n",
 				  dccp_role(sk), sk, len);
 			rc = -EINVAL;
 		} else {
-			opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
-			ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
+			opt_recv->ccid3or_loss_event_rate =
+						ntohl(*(__be32 *)value);
+			ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
 				       dccp_role(sk), sk,
 				       opt_recv->ccid3or_loss_event_rate);
 		}
@@ -602,20 +594,21 @@
 	case TFRC_OPT_LOSS_INTERVALS:
 		opt_recv->ccid3or_loss_intervals_idx = idx;
 		opt_recv->ccid3or_loss_intervals_len = len;
-		ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n",
+		ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
 			       dccp_role(sk), sk,
 			       opt_recv->ccid3or_loss_intervals_idx,
 			       opt_recv->ccid3or_loss_intervals_len);
 		break;
 	case TFRC_OPT_RECEIVE_RATE:
 		if (unlikely(len != 4)) {
-			DCCP_WARN("%s, sk=%p, invalid len %d "
+			DCCP_WARN("%s(%p), invalid len %d "
 				  "for TFRC_OPT_RECEIVE_RATE\n",
 				  dccp_role(sk), sk, len);
 			rc = -EINVAL;
 		} else {
-			opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
-			ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
+			opt_recv->ccid3or_receive_rate =
+						ntohl(*(__be32 *)value);
+			ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
 				       dccp_role(sk), sk,
 				       opt_recv->ccid3or_receive_rate);
 		}
@@ -630,10 +623,12 @@
 	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
 
 	hctx->ccid3hctx_s     = 0;
+	hctx->ccid3hctx_rtt   = 0;
 	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
 	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
 
-	hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
+	hctx->ccid3hctx_no_feedback_timer.function =
+				ccid3_hc_tx_no_feedback_timer;
 	hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
 	init_timer(&hctx->ccid3hctx_no_feedback_timer);
 
@@ -698,8 +693,9 @@
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct dccp_rx_hist_entry *packet;
 	struct timeval now;
+	suseconds_t delta;
 
-	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+	ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
 
 	dccp_timestamp(sk, &now);
 
@@ -707,21 +703,21 @@
 	case TFRC_RSTATE_NO_DATA:
 		hcrx->ccid3hcrx_x_recv = 0;
 		break;
-	case TFRC_RSTATE_DATA: {
-		const u32 delta = timeval_delta(&now,
-					&hcrx->ccid3hcrx_tstamp_last_feedback);
-		hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
-						   delta);
-	}
+	case TFRC_RSTATE_DATA:
+		delta = timeval_delta(&now,
+				      &hcrx->ccid3hcrx_tstamp_last_feedback);
+		DCCP_BUG_ON(delta < 0);
+		hcrx->ccid3hcrx_x_recv =
+			scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
 		break;
 	case TFRC_RSTATE_TERM:
-		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
 		return;
 	}
 
 	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
 	if (unlikely(packet == NULL)) {
-		DCCP_WARN("%s, sk=%p, no data packet in history!\n",
+		DCCP_WARN("%s(%p), no data packet in history!\n",
 			  dccp_role(sk), sk);
 		return;
 	}
@@ -730,13 +726,19 @@
 	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
 	hcrx->ccid3hcrx_bytes_recv	     = 0;
 
-	/* Convert to multiples of 10us */
-	hcrx->ccid3hcrx_elapsed_time =
-			timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
+	/* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */
+	delta = timeval_delta(&now, &packet->dccphrx_tstamp);
+	DCCP_BUG_ON(delta < 0);
+	hcrx->ccid3hcrx_elapsed_time = delta / 10;
+
 	if (hcrx->ccid3hcrx_p == 0)
-		hcrx->ccid3hcrx_pinv = ~0;
-	else
+		hcrx->ccid3hcrx_pinv = ~0U;	/* see RFC 4342, 8.5 */
+	else if (hcrx->ccid3hcrx_p > 1000000) {
+		DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p);
+		hcrx->ccid3hcrx_pinv = 1;	/* use 100% in this case */
+	} else
 		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
+
 	dp->dccps_hc_rx_insert_options = 1;
 	dccp_send_ack(sk);
 }
@@ -764,9 +766,9 @@
 					     hcrx->ccid3hcrx_elapsed_time)) ||
 	    dccp_insert_option_timestamp(sk, skb) ||
 	    dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
-		    	       &pinv, sizeof(pinv)) ||
+			       &pinv, sizeof(pinv)) ||
 	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
-		    	       &x_recv, sizeof(x_recv)))
+			       &x_recv, sizeof(x_recv)))
 		return -1;
 
 	return 0;
@@ -780,12 +782,13 @@
 {
 	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
-	u32 rtt, delta, x_recv, fval, p, tmp2;
+	u32 x_recv, p;
+	suseconds_t rtt, delta;
 	struct timeval tstamp = { 0, };
 	int interval = 0;
 	int win_count = 0;
 	int step = 0;
-	u64 tmp1;
+	u64 fval;
 
 	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
 				 dccphrx_node) {
@@ -810,13 +813,13 @@
 	}
 
 	if (unlikely(step == 0)) {
-		DCCP_WARN("%s, sk=%p, packet history has no data packets!\n",
+		DCCP_WARN("%s(%p), packet history has no data packets!\n",
 			  dccp_role(sk), sk);
 		return ~0;
 	}
 
 	if (unlikely(interval == 0)) {
-		DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0."
+		DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
 			  "Defaulting to 1\n", dccp_role(sk), sk);
 		interval = 1;
 	}
@@ -825,41 +828,51 @@
 		DCCP_CRIT("tail is null\n");
 		return ~0;
 	}
-	rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
-	ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
-		       dccp_role(sk), sk, rtt);
 
-	if (rtt == 0) {
-		DCCP_WARN("RTT==0, setting to 1\n");
- 		rtt = 1;
+	delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+	DCCP_BUG_ON(delta < 0);
+
+	rtt = delta * 4 / interval;
+	ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
+		       dccp_role(sk), sk, (int)rtt);
+
+	/*
+	 * Determine the length of the first loss interval via inverse lookup.
+	 * Assume that X_recv can be computed by the throughput equation
+	 *		    s
+	 *	X_recv = --------
+	 *		 R * fval
+	 * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
+	 */
+	if (rtt == 0) {			/* would result in divide-by-zero */
+		DCCP_WARN("RTT==0, returning 1/p = 1\n");
+		return 1000000;
 	}
 
 	dccp_timestamp(sk, &tstamp);
 	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
-	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
+	DCCP_BUG_ON(delta <= 0);
 
-	if (x_recv == 0)
-		x_recv = hcrx->ccid3hcrx_x_recv;
-
-	tmp1 = (u64)x_recv * (u64)rtt;
-	do_div(tmp1,10000000);
-	tmp2 = (u32)tmp1;
-
-	if (!tmp2) {
-		DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt);
-		return ~0;
+	x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
+	if (x_recv == 0) {		/* would also trigger divide-by-zero */
+		DCCP_WARN("X_recv==0\n");
+		if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
+			DCCP_BUG("stored value of X_recv is zero");
+			return 1000000;
+		}
 	}
 
-	fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
-	/* do not alter order above or you will get overflow on 32 bit */
+	fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
+	fval = scaled_div32(fval, x_recv);
 	p = tfrc_calc_x_reverse_lookup(fval);
-	ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
+
+	ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
 		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
 
 	if (p == 0)
 		return ~0;
 	else
-		return 1000000 / p; 
+		return 1000000 / p;
 }
 
 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
@@ -913,7 +926,8 @@
                                     struct dccp_rx_hist_entry *packet)
 {
 	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-	struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
+	struct dccp_rx_hist_entry *rx_hist =
+				dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
 	u64 seqno = packet->dccphrx_seqno;
 	u64 tmp_seqno;
 	int loss = 0;
@@ -941,7 +955,7 @@
 		dccp_inc_seqno(&tmp_seqno);
 		while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
 		   tmp_seqno, &ccval)) {
-		   	hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+			hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
 			hcrx->ccid3hcrx_ccval_nonloss = ccval;
 			dccp_inc_seqno(&tmp_seqno);
 		}
@@ -967,7 +981,8 @@
 	const struct dccp_options_received *opt_recv;
 	struct dccp_rx_hist_entry *packet;
 	struct timeval now;
-	u32 p_prev, rtt_prev, r_sample, t_elapsed;
+	u32 p_prev, rtt_prev;
+	suseconds_t r_sample, t_elapsed;
 	int loss, payload_size;
 
 	BUG_ON(hcrx == NULL);
@@ -987,11 +1002,13 @@
 		r_sample = timeval_usecs(&now);
 		t_elapsed = opt_recv->dccpor_elapsed_time * 10;
 
+		DCCP_BUG_ON(r_sample < 0);
 		if (unlikely(r_sample <= t_elapsed))
-			DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n",
+			DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
 				  r_sample, t_elapsed);
 		else
 			r_sample -= t_elapsed;
+		CCID3_RTT_SANITY_CHECK(r_sample);
 
 		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
 			hcrx->ccid3hcrx_rtt = r_sample;
@@ -1000,8 +1017,8 @@
 					      r_sample / 10;
 
 		if (rtt_prev != hcrx->ccid3hcrx_rtt)
-			ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
-				       dccp_role(sk), hcrx->ccid3hcrx_rtt,
+			ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",
+				       dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
 				       opt_recv->dccpor_elapsed_time);
 		break;
 	case DCCP_PKT_DATA:
@@ -1013,7 +1030,7 @@
 	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
 					skb, GFP_ATOMIC);
 	if (unlikely(packet == NULL)) {
-		DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet "
+		DCCP_WARN("%s(%p), Not enough mem to add rx packet "
 			  "to history, consider it lost!\n", dccp_role(sk), sk);
 		return;
 	}
@@ -1028,9 +1045,8 @@
 
 	switch (hcrx->ccid3hcrx_state) {
 	case TFRC_RSTATE_NO_DATA:
-		ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
-			       "feedback\n",
-			       dccp_role(sk), sk,
+		ccid3_pr_debug("%s(%p, state=%s), skb=%p, sending initial "
+			       "feedback\n", dccp_role(sk), sk,
 			       dccp_state_name(sk->sk_state), skb);
 		ccid3_hc_rx_send_feedback(sk);
 		ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
@@ -1041,19 +1057,19 @@
 			break;
 
 		dccp_timestamp(sk, &now);
-		if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
-		    hcrx->ccid3hcrx_rtt) {
+		if ((timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) -
+		     (suseconds_t)hcrx->ccid3hcrx_rtt) >= 0) {
 			hcrx->ccid3hcrx_tstamp_last_ack = now;
 			ccid3_hc_rx_send_feedback(sk);
 		}
 		return;
 	case TFRC_RSTATE_TERM:
-		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
 		return;
 	}
 
 	/* Dealing with packet loss */
-	ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
+	ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",
 		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
 
 	p_prev = hcrx->ccid3hcrx_p;
@@ -1078,7 +1094,7 @@
 {
 	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
 
-	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+	ccid3_pr_debug("entry\n");
 
 	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
 	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
@@ -1086,7 +1102,7 @@
 	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
 	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
 	hcrx->ccid3hcrx_s   = 0;
-	hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
+	hcrx->ccid3hcrx_rtt = 0;
 	return 0;
 }
 
@@ -1115,9 +1131,9 @@
 
 	BUG_ON(hcrx == NULL);
 
-	info->tcpi_ca_state	= hcrx->ccid3hcrx_state;
-	info->tcpi_options	|= TCPI_OPT_TIMESTAMPS;
-	info->tcpi_rcv_rtt	= hcrx->ccid3hcrx_rtt;
+	info->tcpi_ca_state = hcrx->ccid3hcrx_state;
+	info->tcpi_options  |= TCPI_OPT_TIMESTAMPS;
+	info->tcpi_rcv_rtt  = hcrx->ccid3hcrx_rtt;
 }
 
 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1198,7 +1214,6 @@
 	.ccid_hc_tx_send_packet	   = ccid3_hc_tx_send_packet,
 	.ccid_hc_tx_packet_sent	   = ccid3_hc_tx_packet_sent,
 	.ccid_hc_tx_packet_recv	   = ccid3_hc_tx_packet_recv,
-	.ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
 	.ccid_hc_tx_parse_options  = ccid3_hc_tx_parse_options,
 	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
 	.ccid_hc_rx_init	   = ccid3_hc_rx_init,
@@ -1210,7 +1225,7 @@
 	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
 	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
 };
- 
+
 #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
 module_param(ccid3_debug, int, 0444);
 MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
@@ -1233,7 +1248,7 @@
 		goto out_free_tx;
 
 	rc = ccid_register(&ccid3);
-	if (rc != 0) 
+	if (rc != 0)
 		goto out_free_loss_interval_history;
 out:
 	return rc;
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 07596d7..15776a8 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -51,6 +51,16 @@
 /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
 #define TFRC_T_MBI		   64
 
+/* What we think is a reasonable upper limit on RTT values */
+#define CCID3_SANE_RTT_MAX	   ((suseconds_t)(4 * USEC_PER_SEC))
+
+#define CCID3_RTT_SANITY_CHECK(rtt) 			do {		   \
+		if (rtt > CCID3_SANE_RTT_MAX) {				   \
+			DCCP_CRIT("RTT (%d) too large, substituting %d",   \
+				  (int)rtt, (int)CCID3_SANE_RTT_MAX);	   \
+			rtt = CCID3_SANE_RTT_MAX;			   \
+		} 					} while (0)
+
 enum ccid3_options {
 	TFRC_OPT_LOSS_EVENT_RATE = 192,
 	TFRC_OPT_LOSS_INTERVALS	 = 193,
@@ -67,7 +77,7 @@
 
 /* TFRC sender states */
 enum ccid3_hc_tx_states {
-       	TFRC_SSTATE_NO_SENT = 1,
+	TFRC_SSTATE_NO_SENT = 1,
 	TFRC_SSTATE_NO_FBACK,
 	TFRC_SSTATE_FBACK,
 	TFRC_SSTATE_TERM,
@@ -75,23 +85,23 @@
 
 /** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket
  *
- * @ccid3hctx_x - Current sending rate
- * @ccid3hctx_x_recv - Receive rate
- * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1)
+ * @ccid3hctx_x - Current sending rate in 64 * bytes per second
+ * @ccid3hctx_x_recv - Receive rate    in 64 * bytes per second
+ * @ccid3hctx_x_calc - Calculated rate in bytes per second
  * @ccid3hctx_rtt - Estimate of current round trip time in usecs
  * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000
- * @ccid3hctx_s - Packet size
- * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1)
- * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6)
+ * @ccid3hctx_s - Packet size in bytes
+ * @ccid3hctx_t_rto - Nofeedback Timer setting in usecs
+ * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) in usecs
  * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states
  * @ccid3hctx_last_win_count - Last window counter sent
  * @ccid3hctx_t_last_win_count - Timestamp of earliest packet
- * 				 with last_win_count value sent
+ *				 with last_win_count value sent
  * @ccid3hctx_no_feedback_timer - Handle to no feedback timer
  * @ccid3hctx_idle - Flag indicating that sender is idling
  * @ccid3hctx_t_ld - Time last doubled during slow start
  * @ccid3hctx_t_nom - Nominal send time of next packet
- * @ccid3hctx_delta - Send timer delta
+ * @ccid3hctx_delta - Send timer delta (RFC 3448, 4.6) in usecs
  * @ccid3hctx_hist - Packet history
  * @ccid3hctx_options_received - Parsed set of retrieved options
  */
@@ -105,7 +115,7 @@
 #define ccid3hctx_t_rto			ccid3hctx_tfrc.tfrctx_rto
 #define ccid3hctx_t_ipi			ccid3hctx_tfrc.tfrctx_ipi
 	u16				ccid3hctx_s;
-  	enum ccid3_hc_tx_states 	ccid3hctx_state:8;
+	enum ccid3_hc_tx_states		ccid3hctx_state:8;
 	u8				ccid3hctx_last_win_count;
 	u8				ccid3hctx_idle;
 	struct timeval			ccid3hctx_t_last_win_count;
@@ -119,7 +129,7 @@
 
 /* TFRC receiver states */
 enum ccid3_hc_rx_states {
-       	TFRC_RSTATE_NO_DATA = 1,
+	TFRC_RSTATE_NO_DATA = 1,
 	TFRC_RSTATE_DATA,
 	TFRC_RSTATE_TERM    = 127,
 };
@@ -147,18 +157,18 @@
 #define ccid3hcrx_x_recv		ccid3hcrx_tfrc.tfrcrx_x_recv
 #define ccid3hcrx_rtt			ccid3hcrx_tfrc.tfrcrx_rtt
 #define ccid3hcrx_p			ccid3hcrx_tfrc.tfrcrx_p
-  	u64				ccid3hcrx_seqno_nonloss:48,
+	u64				ccid3hcrx_seqno_nonloss:48,
 					ccid3hcrx_ccval_nonloss:4,
 					ccid3hcrx_ccval_last_counter:4;
 	enum ccid3_hc_rx_states		ccid3hcrx_state:8;
-  	u32				ccid3hcrx_bytes_recv;
-  	struct timeval			ccid3hcrx_tstamp_last_feedback;
-  	struct timeval			ccid3hcrx_tstamp_last_ack;
+	u32				ccid3hcrx_bytes_recv;
+	struct timeval			ccid3hcrx_tstamp_last_feedback;
+	struct timeval			ccid3hcrx_tstamp_last_ack;
 	struct list_head		ccid3hcrx_hist;
 	struct list_head		ccid3hcrx_li_hist;
-  	u16				ccid3hcrx_s;
-  	u32				ccid3hcrx_pinv;
-  	u32				ccid3hcrx_elapsed_time;
+	u16				ccid3hcrx_s;
+	u32				ccid3hcrx_pinv;
+	u32				ccid3hcrx_elapsed_time;
 };
 
 static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index b876c9c..2e8ef42 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -36,9 +36,100 @@
 
 #include <linux/module.h>
 #include <linux/string.h>
-
 #include "packet_history.h"
 
+/*
+ * 	Transmitter History Routines
+ */
+struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
+{
+	struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
+	static const char dccp_tx_hist_mask[] = "tx_hist_%s";
+	char *slab_name;
+
+	if (hist == NULL)
+		goto out;
+
+	slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
+			    GFP_ATOMIC);
+	if (slab_name == NULL)
+		goto out_free_hist;
+
+	sprintf(slab_name, dccp_tx_hist_mask, name);
+	hist->dccptxh_slab = kmem_cache_create(slab_name,
+					     sizeof(struct dccp_tx_hist_entry),
+					       0, SLAB_HWCACHE_ALIGN,
+					       NULL, NULL);
+	if (hist->dccptxh_slab == NULL)
+		goto out_free_slab_name;
+out:
+	return hist;
+out_free_slab_name:
+	kfree(slab_name);
+out_free_hist:
+	kfree(hist);
+	hist = NULL;
+	goto out;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
+
+void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
+{
+	const char* name = kmem_cache_name(hist->dccptxh_slab);
+
+	kmem_cache_destroy(hist->dccptxh_slab);
+	kfree(name);
+	kfree(hist);
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
+
+struct dccp_tx_hist_entry *
+	dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
+{
+	struct dccp_tx_hist_entry *packet = NULL, *entry;
+
+	list_for_each_entry(entry, list, dccphtx_node)
+		if (entry->dccphtx_seqno == seq) {
+			packet = entry;
+			break;
+		}
+
+	return packet;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
+
+void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
+{
+	struct dccp_tx_hist_entry *entry, *next;
+
+	list_for_each_entry_safe(entry, next, list, dccphtx_node) {
+		list_del_init(&entry->dccphtx_node);
+		dccp_tx_hist_entry_delete(hist, entry);
+	}
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
+
+void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
+			      struct list_head *list,
+			      struct dccp_tx_hist_entry *packet)
+{
+	struct dccp_tx_hist_entry *next;
+
+	list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
+		list_del_init(&packet->dccphtx_node);
+		dccp_tx_hist_entry_delete(hist, packet);
+	}
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
+
+/*
+ * 	Receiver History Routines
+ */
 struct dccp_rx_hist *dccp_rx_hist_new(const char *name)
 {
 	struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
@@ -83,18 +174,24 @@
 
 EXPORT_SYMBOL_GPL(dccp_rx_hist_delete);
 
-void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
+int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+			    u8 *ccval)
 {
-	struct dccp_rx_hist_entry *entry, *next;
+	struct dccp_rx_hist_entry *packet = NULL, *entry;
 
-	list_for_each_entry_safe(entry, next, list, dccphrx_node) {
-		list_del_init(&entry->dccphrx_node);
-		kmem_cache_free(hist->dccprxh_slab, entry);
-	}
+	list_for_each_entry(entry, list, dccphrx_node)
+		if (entry->dccphrx_seqno == seq) {
+			packet = entry;
+			break;
+		}
+
+	if (packet)
+		*ccval = packet->dccphrx_ccval;
+
+	return packet != NULL;
 }
 
-EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
-
+EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
 struct dccp_rx_hist_entry *
 		dccp_rx_hist_find_data_packet(const struct list_head *list)
 {
@@ -184,110 +281,18 @@
 
 EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
 
-struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
+void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
 {
-	struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
-	static const char dccp_tx_hist_mask[] = "tx_hist_%s";
-	char *slab_name;
+	struct dccp_rx_hist_entry *entry, *next;
 
-	if (hist == NULL)
-		goto out;
-
-	slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
-			    GFP_ATOMIC);
-	if (slab_name == NULL)
-		goto out_free_hist;
-
-	sprintf(slab_name, dccp_tx_hist_mask, name);
-	hist->dccptxh_slab = kmem_cache_create(slab_name,
-					     sizeof(struct dccp_tx_hist_entry),
-					       0, SLAB_HWCACHE_ALIGN,
-					       NULL, NULL);
-	if (hist->dccptxh_slab == NULL)
-		goto out_free_slab_name;
-out:
-	return hist;
-out_free_slab_name:
-	kfree(slab_name);
-out_free_hist:
-	kfree(hist);
-	hist = NULL;
-	goto out;
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
-
-void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
-{
-	const char* name = kmem_cache_name(hist->dccptxh_slab);
-
-	kmem_cache_destroy(hist->dccptxh_slab);
-	kfree(name);
-	kfree(hist);
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
-
-struct dccp_tx_hist_entry *
-	dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
-{
-	struct dccp_tx_hist_entry *packet = NULL, *entry;
-
-	list_for_each_entry(entry, list, dccphtx_node)
-		if (entry->dccphtx_seqno == seq) {
-			packet = entry;
-			break;
-		}
-
-	return packet;
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
-
-int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
-   u8 *ccval)
-{
-	struct dccp_rx_hist_entry *packet = NULL, *entry;
-
-	list_for_each_entry(entry, list, dccphrx_node)
-		if (entry->dccphrx_seqno == seq) {
-			packet = entry;
-			break;
-		}
-
-	if (packet)
-		*ccval = packet->dccphrx_ccval;
-
-	return packet != NULL;
-}
-
-EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
-
-void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
-			      struct list_head *list,
-			      struct dccp_tx_hist_entry *packet)
-{
-	struct dccp_tx_hist_entry *next;
-
-	list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
-		list_del_init(&packet->dccphtx_node);
-		dccp_tx_hist_entry_delete(hist, packet);
+	list_for_each_entry_safe(entry, next, list, dccphrx_node) {
+		list_del_init(&entry->dccphrx_node);
+		kmem_cache_free(hist->dccprxh_slab, entry);
 	}
 }
 
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
+EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
 
-void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
-{
-	struct dccp_tx_hist_entry *entry, *next;
-
-	list_for_each_entry_safe(entry, next, list, dccphtx_node) {
-		list_del_init(&entry->dccphtx_node);
-		dccp_tx_hist_entry_delete(hist, entry);
-	}
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
 
 MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
 	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 9a8bcf2..1f960c1 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -49,43 +49,27 @@
 #define TFRC_WIN_COUNT_PER_RTT	 4
 #define TFRC_WIN_COUNT_LIMIT	16
 
+/*
+ * 	Transmitter History data structures and declarations
+ */
 struct dccp_tx_hist_entry {
 	struct list_head dccphtx_node;
 	u64		 dccphtx_seqno:48,
-			 dccphtx_ccval:4,
 			 dccphtx_sent:1;
 	u32		 dccphtx_rtt;
 	struct timeval	 dccphtx_tstamp;
 };
 
-struct dccp_rx_hist_entry {
-	struct list_head dccphrx_node;
-	u64		 dccphrx_seqno:48,
-			 dccphrx_ccval:4,
-			 dccphrx_type:4;
-	u32		 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
-	struct timeval	 dccphrx_tstamp;
-};
-
 struct dccp_tx_hist {
 	struct kmem_cache *dccptxh_slab;
 };
 
 extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name);
-extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist);
-
-struct dccp_rx_hist {
-	struct kmem_cache *dccprxh_slab;
-};
-
-extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
-extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
-extern struct dccp_rx_hist_entry *
-		dccp_rx_hist_find_data_packet(const struct list_head *list);
+extern void 		    dccp_tx_hist_delete(struct dccp_tx_hist *hist);
 
 static inline struct dccp_tx_hist_entry *
-		dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
-				       const gfp_t prio)
+			dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
+					       const gfp_t prio)
 {
 	struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab,
 							    prio);
@@ -96,34 +80,8 @@
 	return entry;
 }
 
-static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
-					     struct dccp_tx_hist_entry *entry)
-{
-	if (entry != NULL)
-		kmem_cache_free(hist->dccptxh_slab, entry);
-}
-
-extern struct dccp_tx_hist_entry *
-			dccp_tx_hist_find_entry(const struct list_head *list,
-						const u64 seq);
-extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
-   u8 *ccval);
-
-static inline void dccp_tx_hist_add_entry(struct list_head *list,
-					  struct dccp_tx_hist_entry *entry)
-{
-	list_add(&entry->dccphtx_node, list);
-}
-
-extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
-				     struct list_head *list,
-				     struct dccp_tx_hist_entry *next);
-
-extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
-			       struct list_head *list);
-
 static inline struct dccp_tx_hist_entry *
-		dccp_tx_hist_head(struct list_head *list)
+			dccp_tx_hist_head(struct list_head *list)
 {
 	struct dccp_tx_hist_entry *head = NULL;
 
@@ -133,12 +91,55 @@
 	return head;
 }
 
+extern struct dccp_tx_hist_entry *
+			dccp_tx_hist_find_entry(const struct list_head *list,
+						const u64 seq);
+
+static inline void dccp_tx_hist_add_entry(struct list_head *list,
+					  struct dccp_tx_hist_entry *entry)
+{
+	list_add(&entry->dccphtx_node, list);
+}
+
+static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
+					     struct dccp_tx_hist_entry *entry)
+{
+	if (entry != NULL)
+		kmem_cache_free(hist->dccptxh_slab, entry);
+}
+
+extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
+			       struct list_head *list);
+
+extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
+				     struct list_head *list,
+				     struct dccp_tx_hist_entry *next);
+
+/*
+ * 	Receiver History data structures and declarations
+ */
+struct dccp_rx_hist_entry {
+	struct list_head dccphrx_node;
+	u64		 dccphrx_seqno:48,
+			 dccphrx_ccval:4,
+			 dccphrx_type:4;
+	u32		 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
+	struct timeval	 dccphrx_tstamp;
+};
+
+struct dccp_rx_hist {
+	struct kmem_cache *dccprxh_slab;
+};
+
+extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
+extern void 		dccp_rx_hist_delete(struct dccp_rx_hist *hist);
+
 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 struct sk_buff *skb,
-					    const gfp_t prio)
+			dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
+					       const struct sock *sk,
+				     	       const u32 ndp,
+					       const struct sk_buff *skb,
+					       const gfp_t prio)
 {
 	struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab,
 							    prio);
@@ -156,6 +157,28 @@
 	return entry;
 }
 
+static inline struct dccp_rx_hist_entry *
+			dccp_rx_hist_head(struct list_head *list)
+{
+	struct dccp_rx_hist_entry *head = NULL;
+
+	if (!list_empty(list))
+		head = list_entry(list->next, struct dccp_rx_hist_entry,
+				  dccphrx_node);
+	return head;
+}
+
+extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+   				   u8 *ccval);
+extern struct dccp_rx_hist_entry *
+		dccp_rx_hist_find_data_packet(const struct list_head *list);
+
+extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+				    struct list_head *rx_list,
+				    struct list_head *li_list,
+				    struct dccp_rx_hist_entry *packet,
+				    u64 nonloss_seqno);
+
 static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
 					     struct dccp_rx_hist_entry *entry)
 {
@@ -166,17 +189,6 @@
 extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
 			       struct list_head *list);
 
-static inline struct dccp_rx_hist_entry *
-		dccp_rx_hist_head(struct list_head *list)
-{
-	struct dccp_rx_hist_entry *head = NULL;
-
-	if (!list_empty(list))
-		head = list_entry(list->next, struct dccp_rx_hist_entry,
-				  dccphrx_node);
-	return head;
-}
-
 static inline int
 	dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
 {
@@ -184,12 +196,6 @@
 	       entry->dccphrx_type == DCCP_PKT_DATAACK;
 }
 
-extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
-				   struct list_head *rx_list,
-				   struct list_head *li_list,
-				   struct dccp_rx_hist_entry *packet,
-				   u64 nonloss_seqno);
-
 extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
 				    struct list_head *li_list, u8 *win_loss);
 
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 45f30f5..faf5f7e 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -13,8 +13,29 @@
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
  */
-
 #include <linux/types.h>
+#include <asm/div64.h>
+
+/* integer-arithmetic divisions of type (a * 1000000)/b */
+static inline u64 scaled_div(u64 a, u32 b)
+{
+	BUG_ON(b==0);
+	a *= 1000000;
+	do_div(a, b);
+	return a;
+}
+
+static inline u32 scaled_div32(u64 a, u32 b)
+{
+	u64 result = scaled_div(a, b);
+
+	if (result > UINT_MAX) {
+		DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U",
+			  (unsigned long long)a, b);
+		return UINT_MAX;
+	}
+	return result;
+}
 
 extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);
 extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index ddac2c5..90009fd 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -13,7 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <asm/div64.h>
 #include "../../dccp.h"
 #include "tfrc.h"
 
@@ -616,15 +615,12 @@
  *  @R: RTT                  scaled by 1000000   (i.e., microseconds)
  *  @p: loss ratio estimate  scaled by 1000000
  *  Returns X_calc           in bytes per second (not scaled).
- *
- * Note: DO NOT alter this code unless you run test cases against it,
- *       as the code has been optimized to stop underflow/overflow.
  */
 u32 tfrc_calc_x(u16 s, u32 R, u32 p)
 {
-	int index;
+	u16 index;
 	u32 f;
-	u64 tmp1, tmp2;
+	u64 result;
 
 	/* check against invalid parameters and divide-by-zero   */
 	BUG_ON(p >  1000000);		/* p must not exceed 100%   */
@@ -650,15 +646,17 @@
 		f = tfrc_calc_x_lookup[index][0];
 	}
 
-	/* The following computes X = s/(R*f(p)) in bytes per second. Since f(p)
-	 * and R are both scaled by 1000000, we need to multiply by 1000000^2.
-	 * ==> DO NOT alter this unless you test against overflow on 32 bit   */
-	tmp1 = ((u64)s * 100000000);
-	tmp2 = ((u64)R * (u64)f);
-	do_div(tmp2, 10000);
-	do_div(tmp1, tmp2); 
-
-	return (u32)tmp1; 
+	/*
+	 * Compute X = s/(R*f(p)) in bytes per second.
+	 * Since f(p) and R are both scaled by 1000000, we need to multiply by
+	 * 1000000^2. To avoid overflow, the result is computed in two stages.
+	 * This works under almost all reasonable operational conditions, for a
+	 * wide range of parameters. Yet, should some strange combination of
+	 * parameters result in overflow, the use of scaled_div32 will catch
+	 * this and return UINT_MAX - which is a logically adequate consequence.
+	 */
+	result = scaled_div(s, R);
+	return scaled_div32(result, f);
 }
 
 EXPORT_SYMBOL_GPL(tfrc_calc_x);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 6888698..a0900bf 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -80,8 +80,6 @@
 
 #define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
 
-#define DCCP_XMIT_TIMEO 30000 /* Time/msecs for blocking transmit per packet */
-
 /* sysctl variables for DCCP */
 extern int  sysctl_dccp_request_retries;
 extern int  sysctl_dccp_retries1;
@@ -434,6 +432,7 @@
 		tv->tv_sec--;
 		tv->tv_usec += USEC_PER_SEC;
 	}
+	DCCP_BUG_ON(tv->tv_sec < 0);
 }
 
 #ifdef CONFIG_SYSCTL
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 4dc487f..95b6927 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -329,7 +329,7 @@
 	switch (type) {
 	case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break;
 	case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break;
-	default: 	     DCCP_WARN("invalid type %d\n", type); return;
+	default:	     DCCP_WARN("invalid type %d\n", type); return;
 
 	}
 	opt->dccpop_feat = feature;
@@ -427,7 +427,7 @@
 	switch (type) {
 	case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break;
 	case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break;
-	default: 	      DCCP_WARN("invalid type %d\n", type);
+	default:	      DCCP_WARN("invalid type %d\n", type);
 			      return 1;
 
 	}
@@ -610,7 +610,7 @@
 	case DCCPO_CHANGE_R:  return("ChangeR");
 	case DCCPO_CONFIRM_R: return("ConfirmR");
 	/* the following case must not appear in feature negotation  */
-	default: 	      dccp_pr_debug("unknown type %d [BUG!]\n", type);
+	default:	      dccp_pr_debug("unknown type %d [BUG!]\n", type);
 	}
 	return NULL;
 }
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 7371a2f..565bc80 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/input.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -82,7 +82,7 @@
 	 *	  Otherwise,
 	 *	     Drop packet and return
 	 */
-	if (dh->dccph_type == DCCP_PKT_SYNC || 
+	if (dh->dccph_type == DCCP_PKT_SYNC ||
 	    dh->dccph_type == DCCP_PKT_SYNCACK) {
 		if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
 			      dp->dccps_awl, dp->dccps_awh) &&
@@ -185,8 +185,8 @@
 		dccp_rcv_close(sk, skb);
 		return 0;
 	case DCCP_PKT_REQUEST:
-		/* Step 7 
-            	 *   or (S.is_server and P.type == Response)
+		/* Step 7
+		 *   or (S.is_server and P.type == Response)
 		 *   or (S.is_client and P.type == Request)
 		 *   or (S.state >= OPEN and P.type == Request
 		 *	and P.seqno >= S.OSR)
@@ -248,8 +248,18 @@
 			    DCCP_ACKVEC_STATE_RECEIVED))
 		goto discard;
 
-	ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
-	ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+	/*
+	 * Deliver to the CCID module in charge.
+	 * FIXME: Currently DCCP operates one-directional only, i.e. a listening
+	 *        server is not at the same time a connecting client. There is
+	 *        not much sense in delivering to both rx/tx sides at the moment
+	 *        (only one is active at a time); when moving to bidirectional
+	 *        service, this needs to be revised.
+	 */
+	if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+		ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+	else
+		ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
 
 	return __dccp_rcv_established(sk, skb, dh, len);
 discard:
@@ -264,7 +274,7 @@
 					       const struct dccp_hdr *dh,
 					       const unsigned len)
 {
-	/* 
+	/*
 	 *  Step 4: Prepare sequence numbers in REQUEST
 	 *     If S.state == REQUEST,
 	 *	  If (P.type == Response or P.type == Reset)
@@ -332,7 +342,7 @@
 		 *	      from the Response * /
 		 *	  S.state := PARTOPEN
 		 *	  Set PARTOPEN timer
-		 * 	  Continue with S.state == PARTOPEN
+		 *	  Continue with S.state == PARTOPEN
 		 *	  / * Step 12 will send the Ack completing the
 		 *	      three-way handshake * /
 		 */
@@ -363,7 +373,7 @@
 			 */
 			__kfree_skb(skb);
 			return 0;
-		} 
+		}
 		dccp_send_ack(sk);
 		return -1;
 	}
@@ -371,7 +381,7 @@
 out_invalid_packet:
 	/* dccp_v4_do_rcv will send a reset */
 	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
-	return 1; 
+	return 1;
 }
 
 static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
@@ -478,14 +488,17 @@
 		if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
 			dccp_event_ack_recv(sk, skb);
 
- 		if (dccp_msk(sk)->dccpms_send_ack_vector &&
+		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 discard;
+				    DCCP_SKB_CB(skb)->dccpd_seq,
+				    DCCP_ACKVEC_STATE_RECEIVED))
+			goto discard;
 
-		ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
-		ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+		/* XXX see the comments in dccp_rcv_established about this */
+		if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+			ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+		else
+			ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
 	}
 
 	/*
@@ -567,7 +580,7 @@
 		}
 	}
 
-	if (!queued) { 
+	if (!queued) {
 discard:
 		__kfree_skb(skb);
 	}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index ff81679..90c74b4 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -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)
@@ -467,7 +467,7 @@
 			    .uli_u = { .ports =
 				       { .sport = dccp_hdr(skb)->dccph_dport,
 					 .dport = dccp_hdr(skb)->dccph_sport }
-			   	     }
+				     }
 			  };
 
 	security_skb_classify_flow(skb, &fl);
@@ -595,7 +595,7 @@
 	struct inet_request_sock *ireq;
 	struct request_sock *req;
 	struct dccp_request_sock *dreq;
- 	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
 	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
 	__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 
@@ -609,7 +609,7 @@
 	if (dccp_bad_service_code(sk, service)) {
 		reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
 		goto drop;
- 	}
+	}
 	/*
 	 * TW buckets are converted to open requests without
 	 * limitations, they conserve resources and peer is
@@ -644,7 +644,7 @@
 	ireq->rmt_addr = skb->nh.iph->saddr;
 	ireq->opt	= NULL;
 
-	/* 
+	/*
 	 * Step 3: Process LISTEN state
 	 *
 	 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
@@ -846,15 +846,15 @@
 	}
 
 	/* Step 2:
-	 * 	Look up flow ID in table and get corresponding socket */
+	 *	Look up flow ID in table and get corresponding socket */
 	sk = __inet_lookup(&dccp_hashinfo,
 			   skb->nh.iph->saddr, dh->dccph_sport,
 			   skb->nh.iph->daddr, dh->dccph_dport,
 			   inet_iif(skb));
 
-	/* 
+	/*
 	 * Step 2:
-	 * 	If no socket ...
+	 *	If no socket ...
 	 */
 	if (sk == NULL) {
 		dccp_pr_debug("failed to look up flow ID in table and "
@@ -862,9 +862,9 @@
 		goto no_dccp_socket;
 	}
 
-	/* 
+	/*
 	 * Step 2:
-	 * 	... or S.state == TIMEWAIT,
+	 *	... or S.state == TIMEWAIT,
 	 *		Generate Reset(No Connection) unless P.type == Reset
 	 *		Drop packet and return
 	 */
@@ -876,8 +876,8 @@
 
 	/*
 	 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
-	 * 	o if MinCsCov = 0, only packets with CsCov = 0 are accepted
-	 * 	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+	 *	o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+	 *	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
 	 */
 	min_cov = dccp_sk(sk)->dccps_pcrlen;
 	if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov))  {
@@ -900,7 +900,7 @@
 		goto discard_it;
 	/*
 	 * Step 2:
-	 * 	If no socket ...
+	 *	If no socket ...
 	 *		Generate Reset(No Connection) unless P.type == Reset
 	 *		Drop packet and return
 	 */
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index c7aaa25..6b91a9d 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -77,7 +77,7 @@
 }
 
 static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-				   		  __be16 sport, __be16 dport   )
+						  __be16 sport, __be16 dport   )
 {
 	return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
 }
@@ -329,7 +329,7 @@
 	skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
 			GFP_ATOMIC);
 	if (skb == NULL)
-	  	return;
+		return;
 
 	skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
 
@@ -353,7 +353,7 @@
 
 	dccp_csum_outgoing(skb);
 	dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
-				   		      &rxskb->nh.ipv6h->daddr);
+						      &rxskb->nh.ipv6h->daddr);
 
 	memset(&fl, 0, sizeof(fl));
 	ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
@@ -424,7 +424,7 @@
 	struct dccp_request_sock *dreq;
 	struct inet6_request_sock *ireq6;
 	struct ipv6_pinfo *np = inet6_sk(sk);
- 	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
 	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
 	__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 
@@ -437,7 +437,7 @@
 	if (dccp_bad_service_code(sk, service)) {
 		reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
 		goto drop;
- 	}
+	}
 	/*
 	 * There are no SYN attacks on IPv6, yet...
 	 */
@@ -787,7 +787,7 @@
 		 * otherwise we just shortcircuit this and continue with
 		 * the new socket..
 		 */
- 		if (nsk != sk) {
+		if (nsk != sk) {
 			if (dccp_child_process(sk, nsk, skb))
 				goto reset;
 			if (opt_skb != NULL)
@@ -843,14 +843,14 @@
 		DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
 
 	/* Step 2:
-	 * 	Look up flow ID in table and get corresponding socket */
+	 *	Look up flow ID in table and get corresponding socket */
 	sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
 			    dh->dccph_sport,
 			    &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
 			    inet6_iif(skb));
 	/*
 	 * Step 2:
-	 * 	If no socket ...
+	 *	If no socket ...
 	 */
 	if (sk == NULL) {
 		dccp_pr_debug("failed to look up flow ID in table and "
@@ -860,7 +860,7 @@
 
 	/*
 	 * Step 2:
-	 * 	... or S.state == TIMEWAIT,
+	 *	... or S.state == TIMEWAIT,
 	 *		Generate Reset(No Connection) unless P.type == Reset
 	 *		Drop packet and return
 	 */
@@ -872,8 +872,8 @@
 
 	/*
 	 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
-	 * 	o if MinCsCov = 0, only packets with CsCov = 0 are accepted
-	 * 	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+	 *	o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+	 *	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
 	 */
 	min_cov = dccp_sk(sk)->dccps_pcrlen;
 	if (dh->dccph_cscov  &&  (min_cov == 0 || dh->dccph_cscov < min_cov))  {
@@ -893,7 +893,7 @@
 		goto discard_it;
 	/*
 	 * Step 2:
-	 * 	If no socket ...
+	 *	If no socket ...
 	 *		Generate Reset(No Connection) unless P.type == Reset
 	 *		Drop packet and return
 	 */
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 4c9e267..6656bb4 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -182,7 +182,7 @@
 
 EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
 
-/* 
+/*
  * Process an incoming packet for RESPOND sockets represented
  * as an request_sock.
  */
diff --git a/net/dccp/options.c b/net/dccp/options.c
index f398b43..c03ba61 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -557,11 +557,6 @@
 			return -1;
 		dp->dccps_hc_rx_insert_options = 0;
 	}
-	if (dp->dccps_hc_tx_insert_options) {
-		if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
-			return -1;
-		dp->dccps_hc_tx_insert_options = 0;
-	}
 
 	/* Feature negotiation */
 	/* Data packets can't do feat negotiation */
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 400c30b..8245696 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/output.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -175,14 +175,12 @@
 /**
  * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet
  * @sk: socket to wait for
- * @timeo: for how long
  */
-static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
-			      long *timeo)
+static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	DEFINE_WAIT(wait);
-	long delay;
+	unsigned long delay;
 	int rc;
 
 	while (1) {
@@ -190,8 +188,6 @@
 
 		if (sk->sk_err)
 			goto do_error;
-		if (!*timeo)
-			goto do_nonblock;
 		if (signal_pending(current))
 			goto do_interrupted;
 
@@ -199,12 +195,9 @@
 		if (rc <= 0)
 			break;
 		delay = msecs_to_jiffies(rc);
-		if (delay > *timeo || delay < 0)
-			goto do_nonblock;
-
 		sk->sk_write_pending++;
 		release_sock(sk);
-		*timeo -= schedule_timeout(delay);
+		schedule_timeout(delay);
 		lock_sock(sk);
 		sk->sk_write_pending--;
 	}
@@ -215,11 +208,8 @@
 do_error:
 	rc = -EPIPE;
 	goto out;
-do_nonblock:
-	rc = -EAGAIN;
-	goto out;
 do_interrupted:
-	rc = sock_intr_errno(*timeo);
+	rc = -EINTR;
 	goto out;
 }
 
@@ -240,8 +230,6 @@
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct sk_buff *skb;
-	long timeo = DCCP_XMIT_TIMEO; 	/* If a packet is taking longer than
-					   this we have other issues */
 
 	while ((skb = skb_peek(&sk->sk_write_queue))) {
 		int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
@@ -251,11 +239,9 @@
 				sk_reset_timer(sk, &dp->dccps_xmit_timer,
 						msecs_to_jiffies(err)+jiffies);
 				break;
-			} else {
-				err = dccp_wait_for_ccid(sk, skb, &timeo);
-				timeo = DCCP_XMIT_TIMEO;
-			}
-			if (err)
+			} else
+				err = dccp_wait_for_ccid(sk, skb);
+			if (err && err != -EINTR)
 				DCCP_BUG("err=%d after dccp_wait_for_ccid", err);
 		}
 
@@ -281,8 +267,10 @@
 			if (err)
 				DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",
 					 err);
-		} else
+		} else {
+			dccp_pr_debug("packet discarded\n");
 			kfree(skb);
+		}
 	}
 }
 
@@ -350,7 +338,6 @@
 
 static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
 				       const enum dccp_reset_codes code)
-				   
 {
 	struct dccp_hdr *dh;
 	struct dccp_sock *dp = dccp_sk(sk);
@@ -431,14 +418,14 @@
 	
 	dccp_sync_mss(sk, dst_mtu(dst));
 
- 	/*
+	/*
 	 * SWL and AWL are initially adjusted so that they are not less than
 	 * the initial Sequence Numbers received and sent, respectively:
 	 *	SWL := max(GSR + 1 - floor(W/4), ISR),
 	 *	AWL := max(GSS - W' + 1, ISS).
 	 * These adjustments MUST be applied only at the beginning of the
 	 * connection.
- 	 */
+	 */
 	dccp_update_gss(sk, dp->dccps_iss);
 	dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
 
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 5ec47d9..63b3fa2 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -196,7 +196,7 @@
 						      sk, GFP_KERNEL);
 		dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
 						      sk, GFP_KERNEL);
-	    	if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
+		if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
 			     dp->dccps_hc_tx_ccid == NULL)) {
 			ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
 			ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
@@ -390,7 +390,7 @@
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct dccp_service_list *sl = NULL;
 
-	if (service == DCCP_SERVICE_INVALID_VALUE || 
+	if (service == DCCP_SERVICE_INVALID_VALUE ||
 	    optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32))
 		return -EINVAL;
 
@@ -830,7 +830,7 @@
 static const unsigned char dccp_new_state[] = {
 	/* current state:   new state:      action:	*/
 	[0]		  = DCCP_CLOSED,
-	[DCCP_OPEN] 	  = DCCP_CLOSING | DCCP_ACTION_FIN,
+	[DCCP_OPEN]	  = DCCP_CLOSING | DCCP_ACTION_FIN,
 	[DCCP_REQUESTING] = DCCP_CLOSED,
 	[DCCP_PARTOPEN]	  = DCCP_CLOSING | DCCP_ACTION_FIN,
 	[DCCP_LISTEN]	  = DCCP_CLOSED,
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index e8f519e..e5348f3 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/timer.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -102,13 +102,13 @@
 	 * sk->sk_send_head has to have one skb with
 	 * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
 	 * packet types. The only packets eligible for retransmission are:
-	 * 	-- Requests in client-REQUEST  state (sec. 8.1.1)
-	 * 	-- Acks     in client-PARTOPEN state (sec. 8.1.5)
-	 * 	-- CloseReq in server-CLOSEREQ state (sec. 8.3)
-	 * 	-- Close    in   node-CLOSING  state (sec. 8.3)                */
+	 *	-- Requests in client-REQUEST  state (sec. 8.1.1)
+	 *	-- Acks     in client-PARTOPEN state (sec. 8.1.5)
+	 *	-- CloseReq in server-CLOSEREQ state (sec. 8.3)
+	 *	-- Close    in   node-CLOSING  state (sec. 8.3)                */
 	BUG_TRAP(sk->sk_send_head != NULL);
 
-	/* 
+	/*
 	 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
 	 * sent, no need to retransmit, this sock is dead.
 	 */
@@ -200,7 +200,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;
 	}
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 91a075e..7ea2d98 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -657,7 +657,7 @@
 		if (stop_master_sync)
 			break;
 
-		ssleep(1);
+		msleep_interruptible(1000);
 	}
 
 	/* clean up the sync_buff queue */
@@ -714,7 +714,7 @@
 		if (stop_backup_sync)
 			break;
 
-		ssleep(1);
+		msleep_interruptible(1000);
 	}
 
 	/* release the sending multicast socket */
@@ -826,7 +826,7 @@
 	if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
 		IP_VS_ERR("could not create sync_thread due to %d... "
 			  "retrying.\n", pid);
-		ssleep(1);
+		msleep_interruptible(1000);
 		goto repeat;
 	}
 
@@ -849,10 +849,12 @@
 
 	ip_vs_sync_state |= state;
 	if (state == IP_VS_STATE_MASTER) {
-		strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn));
+		strlcpy(ip_vs_master_mcast_ifn, mcast_ifn,
+			sizeof(ip_vs_master_mcast_ifn));
 		ip_vs_master_syncid = syncid;
 	} else {
-		strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn));
+		strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn,
+			sizeof(ip_vs_backup_mcast_ifn));
 		ip_vs_backup_syncid = syncid;
 	}
 
@@ -860,7 +862,7 @@
 	if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
 		IP_VS_ERR("could not create fork_sync_thread due to %d... "
 			  "retrying.\n", pid);
-		ssleep(1);
+		msleep_interruptible(1000);
 		goto repeat;
 	}
 
@@ -880,7 +882,8 @@
 
 	IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
 	IP_VS_INFO("stopping sync thread %d ...\n",
-		   (state == IP_VS_STATE_MASTER) ? sync_master_pid : sync_backup_pid);
+		   (state == IP_VS_STATE_MASTER) ?
+		   sync_master_pid : sync_backup_pid);
 
 	__set_current_state(TASK_UNINTERRUPTIBLE);
 	add_wait_queue(&stop_sync_wait, &wait);
diff --git a/sound/Kconfig b/sound/Kconfig
index 95949b6..9d77300 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -93,4 +93,12 @@
 
 endif
 
+config AC97_BUS
+	tristate
+	help
+	  This is used to avoid config and link hard dependencies between the
+	  sound subsystem and other function drivers completely unrelated to
+	  sound although they're sharing the AC97 bus. Concerned drivers
+	  should "select" this.
+
 endmenu
diff --git a/sound/Makefile b/sound/Makefile
index 5f6bef5..9aee54c 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -8,6 +8,9 @@
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
 obj-$(CONFIG_SND_AOA) += aoa/
 
+# This one must be compilable even if sound is configured out
+obj-$(CONFIG_AC97_BUS) += ac97_bus.o
+
 ifeq ($(CONFIG_SND),y)
   obj-y += last.o
 endif
diff --git a/sound/pci/ac97/ac97_bus.c b/sound/ac97_bus.c
similarity index 100%
rename from sound/pci/ac97/ac97_bus.c
rename to sound/ac97_bus.c
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7971285..40ebd2f 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -26,11 +26,7 @@
 config SND_AC97_CODEC
 	tristate
 	select SND_PCM
-	select SND_AC97_BUS
-
-config SND_AC97_BUS
-	tristate
-
+	select AC97_BUS
 
 config SND_DUMMY
 	tristate "Dummy (/dev/null) soundcard"
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
index 77b3482..3c32221 100644
--- a/sound/pci/ac97/Makefile
+++ b/sound/pci/ac97/Makefile
@@ -10,11 +10,9 @@
 endif
 
 snd-ak4531-codec-objs := ak4531_codec.o
-snd-ac97-bus-objs := ac97_bus.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o
 obj-$(CONFIG_SND_ENS1370) += snd-ak4531-codec.o
-obj-$(CONFIG_SND_AC97_BUS) += snd-ac97-bus.o
 
 obj-m := $(sort $(obj-m))