Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 475950c..ee8a9ad 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -67,10 +67,6 @@
 config GENERIC_ISA_DMA
 	bool
 
-config GENERIC_IOMAP
-	bool
-	default y
-
 config FIQ
 	bool
 
@@ -202,6 +198,11 @@
 	help
 	  This enables support for systems based on the Hynix HMS720x
 
+config ARCH_AAEC2000
+	bool "Agilent AAEC-2000 based"
+	help
+	  This enables support for systems based on the Agilent AAEC-2000
+
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -234,6 +235,8 @@
 
 source "arch/arm/mach-versatile/Kconfig"
 
+source "arch/arm/mach-aaec2000/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -277,7 +280,7 @@
 	default y
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 2277e3d..8330495 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -97,6 +97,7 @@
  machine-$(CONFIG_ARCH_VERSATILE)  := versatile
  machine-$(CONFIG_ARCH_IMX)	   := imx
  machine-$(CONFIG_ARCH_H720X)	   := h720x
+ machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5797b1b..9d63a01 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -30,6 +30,8 @@
 #include <linux/dmapool.h>
 #include <linux/list.h>
 
+#include <asm/cacheflush.h>
+
 #undef DEBUG
 
 #undef STATS
@@ -302,12 +304,24 @@
 
 		DO_STATS ( device_info->bounce_count++ );
 
-		if ((dir == DMA_FROM_DEVICE) ||
-		    (dir == DMA_BIDIRECTIONAL)) {
+		if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+			unsigned long ptr;
+
 			dev_dbg(dev,
 				"%s: copy back safe %p to unsafe %p size %d\n",
 				__func__, buf->safe, buf->ptr, size);
 			memcpy(buf->ptr, buf->safe, size);
+
+			/*
+			 * DMA buffers must have the same cache properties
+			 * as if they were really used for DMA - which means
+			 * data must be written back to RAM.  Note that
+			 * we don't use dmac_flush_range() here for the
+			 * bidirectional case because we know the cache
+			 * lines will be coherent with the data written.
+			 */
+			ptr = (unsigned long)buf->ptr;
+			dmac_clean_range(ptr, ptr + size);
 		}
 		free_safe_buffer(device_info, buf);
 	}
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c
index c2c557a..c94864c 100644
--- a/arch/arm/common/sharpsl_param.c
+++ b/arch/arm/common/sharpsl_param.c
@@ -22,7 +22,7 @@
  * them early in the boot process, then pass them to the appropriate drivers.
  * Not all devices use all paramaters but the format is common to all.
  */
-#ifdef ARCH_SA1100
+#ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE	0xe8ffc000
 #else
 #define PARAM_BASE	0xa0000a00
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index e8f9fcc..06fae4b 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -50,7 +50,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 4fd663e..810a450 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -50,7 +50,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 6f51c98..72e1b94 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -50,7 +50,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index 7be3521..1592e45 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -50,7 +50,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index cd84a20..f1afe3d 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -50,7 +50,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 4a2af55..3e1b032 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -6,7 +6,7 @@
 
 # Object file lists.
 
-obj-y		:= arch.o compat.o dma.o entry-armv.o entry-common.o irq.o   \
+obj-y		:= compat.o dma.o entry-armv.o entry-common.o irq.o \
 		   process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
 		   time.o traps.o
 
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
deleted file mode 100644
index 4e02fbe..0000000
--- a/arch/arm/kernel/arch.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  linux/arch/arm/kernel/arch.c
- *
- *  Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/elf.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/mach/arch.h>
-
-unsigned int vram_size;
-
-#ifdef CONFIG_ARCH_ACORN
-
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-
-static int __init parse_tag_acorn(const struct tag *tag)
-{
-	memc_ctrl_reg = tag->u.acorn.memc_control_reg;
-	number_mfm_drives = tag->u.acorn.adfsdrives;
-
-	switch (tag->u.acorn.vram_pages) {
-	case 512:
-		vram_size += PAGE_SIZE * 256;
-	case 256:
-		vram_size += PAGE_SIZE * 256;
-	default:
-		break;
-	}
-#if 0
-	if (vram_size) {
-		desc->video_start = 0x02000000;
-		desc->video_end   = 0x02000000 + vram_size;
-	}
-#endif
-	return 0;
-}
-
-__tagtable(ATAG_ACORN, parse_tag_acorn);
-
-#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 45ed036..3489275 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -145,7 +145,8 @@
 	pgd_free(pgd);
 
 	if (ret) {
-		printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
+		printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
+
 		/*
 		 * FIXME: We need to clean up the new idle thread. --rmk
 		 */
diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c
index 130f5a8..b62875c 100644
--- a/arch/arm/lib/ashldi3.c
+++ b/arch/arm/lib/ashldi3.c
@@ -31,31 +31,26 @@
 
 #include "gcclib.h"
 
-DItype
-__ashldi3 (DItype u, word_type b)
+s64 __ashldi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
+	DIunion w;
+	int bm;
+	DIunion uu;
 
-  if (b == 0)
-    return u;
+	if (b == 0)
+		return u;
 
-  uu.ll = u;
+	uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.low = 0;
-      w.s.high = (USItype)uu.s.low << -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.low >> bm;
-      w.s.low = (USItype)uu.s.low << b;
-      w.s.high = ((USItype)uu.s.high << b) | carries;
-    }
+	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (u32) uu.s.low << -bm;
+	} else {
+		u32 carries = (u32) uu.s.low >> bm;
+		w.s.low = (u32) uu.s.low << b;
+		w.s.high = ((u32) uu.s.high << b) | carries;
+	}
 
-  return w.ll;
+	return w.ll;
 }
-
diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c
index 71625d2..9a8600a 100644
--- a/arch/arm/lib/ashrdi3.c
+++ b/arch/arm/lib/ashrdi3.c
@@ -31,31 +31,27 @@
 
 #include "gcclib.h"
 
-DItype
-__ashrdi3 (DItype u, word_type b)
+s64 __ashrdi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
+	DIunion w;
+	int bm;
+	DIunion uu;
 
-  if (b == 0)
-    return u;
+	if (b == 0)
+		return u;
 
-  uu.ll = u;
+	uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
-      w.s.low = uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
+	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		u32 carries = (u32) uu.s.high << bm;
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((u32) uu.s.low >> b) | carries;
+	}
 
-  return w.ll;
+	return w.ll;
 }
diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h
index 65314a3..8b6dcc6 100644
--- a/arch/arm/lib/gcclib.h
+++ b/arch/arm/lib/gcclib.h
@@ -1,25 +1,22 @@
 /* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
 /* I Molton     29/07/01 */
 
-#define BITS_PER_UNIT  8
-#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#include <linux/types.h>
 
-typedef unsigned int UQItype    __attribute__ ((mode (QI)));
-typedef          int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype    __attribute__ ((mode (SI)));
-typedef          int DItype     __attribute__ ((mode (DI)));
-typedef          int word_type 	__attribute__ ((mode (__word__)));
-typedef unsigned int UDItype    __attribute__ ((mode (DI)));
+#define BITS_PER_UNIT	8
+#define SI_TYPE_SIZE	(sizeof(s32) * BITS_PER_UNIT)
 
 #ifdef __ARMEB__
-  struct DIstruct {SItype high, low;};
+struct DIstruct {
+	s32 high, low;
+};
 #else
-  struct DIstruct {SItype low, high;};
+struct DIstruct {
+	s32 low, high;
+};
 #endif
 
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
+typedef union {
+	struct DIstruct s;
+	s64 ll;
 } DIunion;
-
diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h
index 179eea4..90ae647 100644
--- a/arch/arm/lib/longlong.h
+++ b/arch/arm/lib/longlong.h
@@ -26,18 +26,18 @@
 
 #define __BITS4 (SI_TYPE_SIZE / 4)
 #define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+#define __ll_lowpart(t) ((u32) (t) % __ll_B)
+#define __ll_highpart(t) ((u32) (t) / __ll_B)
 
 /* Define auxiliary asm macros.
 
    1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
-   multiplies two USItype integers MULTIPLER and MULTIPLICAND,
-   and generates a two-part USItype product in HIGH_PROD and
+   multiplies two u32 integers MULTIPLER and MULTIPLICAND,
+   and generates a two-part u32 product in HIGH_PROD and
    LOW_PROD.
 
-   2) __umulsidi3(a,b) multiplies two USItype integers A and B,
-   and returns a UDItype product.  This is just a variant of umul_ppmm.
+   2) __umulsidi3(a,b) multiplies two u32 integers A and B,
+   and returns a u64 product.  This is just a variant of umul_ppmm.
 
    3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
    denominator) divides a two-word unsigned integer, composed by the
@@ -77,23 +77,23 @@
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   __asm__ ("adds	%1, %4, %5					\n\
 	adc	%0, %2, %3"						\
-	   : "=r" ((USItype) (sh)),					\
-	     "=&r" ((USItype) (sl))					\
-	   : "%r" ((USItype) (ah)),					\
-	     "rI" ((USItype) (bh)),					\
-	     "%r" ((USItype) (al)),					\
-	     "rI" ((USItype) (bl)))
+	   : "=r" ((u32) (sh)),					\
+	     "=&r" ((u32) (sl))					\
+	   : "%r" ((u32) (ah)),					\
+	     "rI" ((u32) (bh)),					\
+	     "%r" ((u32) (al)),					\
+	     "rI" ((u32) (bl)))
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
   __asm__ ("subs	%1, %4, %5					\n\
 	sbc	%0, %2, %3"						\
-	   : "=r" ((USItype) (sh)),					\
-	     "=&r" ((USItype) (sl))					\
-	   : "r" ((USItype) (ah)),					\
-	     "rI" ((USItype) (bh)),					\
-	     "r" ((USItype) (al)),					\
-	     "rI" ((USItype) (bl)))
+	   : "=r" ((u32) (sh)),					\
+	     "=&r" ((u32) (sl))					\
+	   : "r" ((u32) (ah)),					\
+	     "rI" ((u32) (bh)),					\
+	     "r" ((u32) (al)),					\
+	     "rI" ((u32) (bl)))
 #define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2;					\
+{register u32 __t0, __t1, __t2;					\
   __asm__ ("%@ Inlined umul_ppmm					\n\
 	mov	%2, %5, lsr #16						\n\
 	mov	%0, %6, lsr #16						\n\
@@ -107,14 +107,14 @@
 	addcs	%0, %0, #65536						\n\
 	adds	%1, %1, %3, lsl #16					\n\
 	adc	%0, %0, %3, lsr #16"					\
-	   : "=&r" ((USItype) (xh)),					\
-	     "=r" ((USItype) (xl)),					\
+	   : "=&r" ((u32) (xh)),					\
+	     "=r" ((u32) (xl)),					\
 	     "=&r" (__t0), "=&r" (__t1), "=r" (__t2)			\
-	   : "r" ((USItype) (a)),					\
-	     "r" ((USItype) (b)));}
+	   : "r" ((u32) (a)),					\
+	     "r" ((u32) (b)));}
 #define UMUL_TIME 20
 #define UDIV_TIME 100
-#endif /* __arm__ */
+#endif				/* __arm__ */
 
 #define __umulsidi3(u, v) \
   ({DIunion __w;							\
@@ -123,14 +123,14 @@
 
 #define __udiv_qrnnd_c(q, r, n1, n0, d) \
   do {									\
-    USItype __d1, __d0, __q1, __q0;					\
-    USItype __r1, __r0, __m;						\
+    u32 __d1, __d0, __q1, __q0;					\
+    u32 __r1, __r0, __m;						\
     __d1 = __ll_highpart (d);						\
     __d0 = __ll_lowpart (d);						\
 									\
     __r1 = (n1) % __d1;							\
     __q1 = (n1) / __d1;							\
-    __m = (USItype) __q1 * __d0;					\
+    __m = (u32) __q1 * __d0;					\
     __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
     if (__r1 < __m)							\
       {									\
@@ -143,7 +143,7 @@
 									\
     __r0 = __r1 % __d1;							\
     __q0 = __r1 / __d1;							\
-    __m = (USItype) __q0 * __d0;					\
+    __m = (u32) __q0 * __d0;					\
     __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
     if (__r0 < __m)							\
       {									\
@@ -154,7 +154,7 @@
       }									\
     __r0 -= __m;							\
 									\
-    (q) = (USItype) __q1 * __ll_B | __q0;				\
+    (q) = (u32) __q1 * __ll_B | __q0;				\
     (r) = __r0;								\
   } while (0)
 
@@ -163,14 +163,14 @@
 
 #define count_leading_zeros(count, x) \
   do {									\
-    USItype __xr = (x);							\
-    USItype __a;							\
+    u32 __xr = (x);							\
+    u32 __a;							\
 									\
     if (SI_TYPE_SIZE <= 32)						\
       {									\
-	__a = __xr < ((USItype)1<<2*__BITS4)				\
-	  ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4)		\
-	  : (__xr < ((USItype)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
+	__a = __xr < ((u32)1<<2*__BITS4)				\
+	  ? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4)		\
+	  : (__xr < ((u32)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
       }									\
     else								\
       {									\
diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c
index b666f1b..3681f49d 100644
--- a/arch/arm/lib/lshrdi3.c
+++ b/arch/arm/lib/lshrdi3.c
@@ -31,31 +31,26 @@
 
 #include "gcclib.h"
 
-DItype
-__lshrdi3 (DItype u, word_type b)
+s64 __lshrdi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
+	DIunion w;
+	int bm;
+	DIunion uu;
 
-  if (b == 0)
-    return u;
+	if (b == 0)
+		return u;
 
-  uu.ll = u;
+	uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.high = 0;
-      w.s.low = (USItype)uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = (USItype)uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
+	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (u32) uu.s.high >> -bm;
+	} else {
+		u32 carries = (u32) uu.s.high << bm;
+		w.s.high = (u32) uu.s.high >> b;
+		w.s.low = ((u32) uu.s.low >> b) | carries;
+	}
 
-  return w.ll;
+	return w.ll;
 }
-
diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c
index 44d611b..0a3b933 100644
--- a/arch/arm/lib/muldi3.c
+++ b/arch/arm/lib/muldi3.c
@@ -32,7 +32,7 @@
 #include "gcclib.h"
 
 #define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2;                                     \
+{register u32 __t0, __t1, __t2;                                     \
   __asm__ ("%@ Inlined umul_ppmm					\n\
         mov     %2, %5, lsr #16						\n\
         mov     %0, %6, lsr #16						\n\
@@ -46,32 +46,27 @@
         addcs   %0, %0, #65536						\n\
         adds    %1, %1, %3, lsl #16					\n\
         adc     %0, %0, %3, lsr #16"                                    \
-           : "=&r" ((USItype) (xh)),                                    \
-             "=r" ((USItype) (xl)),                                     \
+           : "=&r" ((u32) (xh)),                                    \
+             "=r" ((u32) (xl)),                                     \
              "=&r" (__t0), "=&r" (__t1), "=r" (__t2)                    \
-           : "r" ((USItype) (a)),                                       \
-             "r" ((USItype) (b)));}
-
+           : "r" ((u32) (a)),                                       \
+             "r" ((u32) (b)));}
 
 #define __umulsidi3(u, v) \
   ({DIunion __w;                                                        \
     umul_ppmm (__w.s.high, __w.s.low, u, v);                            \
     __w.ll; })
 
-
-DItype
-__muldi3 (DItype u, DItype v)
+s64 __muldi3(s64 u, s64 v)
 {
-  DIunion w;
-  DIunion uu, vv;
+	DIunion w;
+	DIunion uu, vv;
 
-  uu.ll = u,
-  vv.ll = v;
+	uu.ll = u, vv.ll = v;
 
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-               + (USItype) uu.s.high * (USItype) vv.s.low);
+	w.ll = __umulsidi3(uu.s.low, vv.s.low);
+	w.s.high += ((u32) uu.s.low * (u32) vv.s.high
+		     + (u32) uu.s.high * (u32) vv.s.low);
 
-  return w.ll;
+	return w.ll;
 }
-
diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c
index 6c6ae63..57f3f2d 100644
--- a/arch/arm/lib/ucmpdi2.c
+++ b/arch/arm/lib/ucmpdi2.c
@@ -31,21 +31,19 @@
 
 #include "gcclib.h"
 
-word_type
-__ucmpdi2 (DItype a, DItype b)
+int __ucmpdi2(s64 a, s64 b)
 {
-  DIunion au, bu;
+	DIunion au, bu;
 
-  au.ll = a, bu.ll = b;
+	au.ll = a, bu.ll = b;
 
-  if ((USItype) au.s.high < (USItype) bu.s.high)
-    return 0;
-  else if ((USItype) au.s.high > (USItype) bu.s.high)
-    return 2;
-  if ((USItype) au.s.low < (USItype) bu.s.low)
-    return 0;
-  else if ((USItype) au.s.low > (USItype) bu.s.low)
-    return 2;
-  return 1;
+	if ((u32) au.s.high < (u32) bu.s.high)
+		return 0;
+	else if ((u32) au.s.high > (u32) bu.s.high)
+		return 2;
+	if ((u32) au.s.low < (u32) bu.s.low)
+		return 0;
+	else if ((u32) au.s.low > (u32) bu.s.low)
+		return 2;
+	return 1;
 }
-
diff --git a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c
index d25195f..e343be4 100644
--- a/arch/arm/lib/udivdi3.c
+++ b/arch/arm/lib/udivdi3.c
@@ -32,211 +32,191 @@
 #include "gcclib.h"
 #include "longlong.h"
 
-static const UQItype __clz_tab[] =
-{
-  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+static const u8 __clz_tab[] = {
+	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+	    5, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	    6, 6, 6, 6, 6, 6, 6, 6,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	    7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	    7, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
 };
 
-UDItype
-__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
+u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
 {
-  DIunion ww;
-  DIunion nn, dd;
-  DIunion rr;
-  USItype d0, d1, n0, n1, n2;
-  USItype q0, q1;
-  USItype b, bm;
+	DIunion ww;
+	DIunion nn, dd;
+	DIunion rr;
+	u32 d0, d1, n0, n1, n2;
+	u32 q0, q1;
+	u32 b, bm;
 
-  nn.ll = n;
-  dd.ll = d;
+	nn.ll = n;
+	dd.ll = d;
 
-  d0 = dd.s.low;
-  d1 = dd.s.high;
-  n0 = nn.s.low;
-  n1 = nn.s.high;
+	d0 = dd.s.low;
+	d1 = dd.s.high;
+	n0 = nn.s.low;
+	n1 = nn.s.high;
 
-  if (d1 == 0)
-    {
-      if (d0 > n1)
-        {
-          /* 0q = nn / 0D */
+	if (d1 == 0) {
+		if (d0 > n1) {
+			/* 0q = nn / 0D */
 
-          count_leading_zeros (bm, d0);
+			count_leading_zeros(bm, d0);
 
-          if (bm != 0)
-            {
-              /* Normalize, i.e. make the most significant bit of the
-                 denominator set.  */
+			if (bm != 0) {
+				/* Normalize, i.e. make the most significant bit of the
+				   denominator set.  */
 
-              d0 = d0 << bm;
-              n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
-              n0 = n0 << bm;
-            }
+				d0 = d0 << bm;
+				n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+				n0 = n0 << bm;
+			}
 
-          udiv_qrnnd (q0, n0, n1, n0, d0);
-          q1 = 0;
+			udiv_qrnnd(q0, n0, n1, n0, d0);
+			q1 = 0;
 
-          /* Remainder in n0 >> bm.  */
-        }
-      else
-        {
-          /* qq = NN / 0d */
+			/* Remainder in n0 >> bm.  */
+		} else {
+			/* qq = NN / 0d */
 
-          if (d0 == 0)
-            d0 = 1 / d0;        /* Divide intentionally by zero.  */
+			if (d0 == 0)
+				d0 = 1 / d0;	/* Divide intentionally by zero.  */
 
-          count_leading_zeros (bm, d0);
+			count_leading_zeros(bm, d0);
 
-          if (bm == 0)
-            {
-              /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
-                 conclude (the most significant bit of n1 is set) /\ (the
-                 leading quotient digit q1 = 1).
+			if (bm == 0) {
+				/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+				   conclude (the most significant bit of n1 is set) /\ (the
+				   leading quotient digit q1 = 1).
 
-                 This special case is necessary, not an optimization.
-                 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
+				   This special case is necessary, not an optimization.
+				   (Shifts counts of SI_TYPE_SIZE are undefined.)  */
 
-              n1 -= d0;
-              q1 = 1;
-            }
-          else
-            {
-              /* Normalize.  */
+				n1 -= d0;
+				q1 = 1;
+			} else {
+				/* Normalize.  */
 
-              b = SI_TYPE_SIZE - bm;
+				b = SI_TYPE_SIZE - bm;
 
-              d0 = d0 << bm;
-              n2 = n1 >> b;
-              n1 = (n1 << bm) | (n0 >> b);
-              n0 = n0 << bm;
+				d0 = d0 << bm;
+				n2 = n1 >> b;
+				n1 = (n1 << bm) | (n0 >> b);
+				n0 = n0 << bm;
 
-              udiv_qrnnd (q1, n1, n2, n1, d0);
-            }
+				udiv_qrnnd(q1, n1, n2, n1, d0);
+			}
 
-          /* n1 != d0...  */
+			/* n1 != d0...  */
 
-          udiv_qrnnd (q0, n0, n1, n0, d0);
+			udiv_qrnnd(q0, n0, n1, n0, d0);
 
-          /* Remainder in n0 >> bm.  */
-        }
+			/* Remainder in n0 >> bm.  */
+		}
 
-      if (rp != 0)
-        {
-          rr.s.low = n0 >> bm;
-          rr.s.high = 0;
-          *rp = rr.ll;
-        }
-    }
-  else
-    {
-      if (d1 > n1)
-        {
-          /* 00 = nn / DD */
+		if (rp != 0) {
+			rr.s.low = n0 >> bm;
+			rr.s.high = 0;
+			*rp = rr.ll;
+		}
+	} else {
+		if (d1 > n1) {
+			/* 00 = nn / DD */
 
-          q0 = 0;
-          q1 = 0;
+			q0 = 0;
+			q1 = 0;
 
-          /* Remainder in n1n0.  */
-          if (rp != 0)
-            {
-              rr.s.low = n0;
-              rr.s.high = n1;
-              *rp = rr.ll;
-            }
-        }
-      else
-        {
-          /* 0q = NN / dd */
+			/* Remainder in n1n0.  */
+			if (rp != 0) {
+				rr.s.low = n0;
+				rr.s.high = n1;
+				*rp = rr.ll;
+			}
+		} else {
+			/* 0q = NN / dd */
 
-          count_leading_zeros (bm, d1);
-          if (bm == 0)
-            {
-              /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
-                 conclude (the most significant bit of n1 is set) /\ (the
-                 quotient digit q0 = 0 or 1).
+			count_leading_zeros(bm, d1);
+			if (bm == 0) {
+				/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+				   conclude (the most significant bit of n1 is set) /\ (the
+				   quotient digit q0 = 0 or 1).
 
-                 This special case is necessary, not an optimization.  */
+				   This special case is necessary, not an optimization.  */
 
-              /* The condition on the next line takes advantage of that
-                 n1 >= d1 (true due to program flow).  */
-              if (n1 > d1 || n0 >= d0)
-                {
-                  q0 = 1;
-                  sub_ddmmss (n1, n0, n1, n0, d1, d0);
-                }
-              else
-                q0 = 0;
+				/* The condition on the next line takes advantage of that
+				   n1 >= d1 (true due to program flow).  */
+				if (n1 > d1 || n0 >= d0) {
+					q0 = 1;
+					sub_ddmmss(n1, n0, n1, n0, d1, d0);
+				} else
+					q0 = 0;
 
-              q1 = 0;
+				q1 = 0;
 
-              if (rp != 0)
-                {
-                  rr.s.low = n0;
-                  rr.s.high = n1;
-                  *rp = rr.ll;
-                }
-            }
-          else
-            {
-              USItype m1, m0;
-              /* Normalize.  */
+				if (rp != 0) {
+					rr.s.low = n0;
+					rr.s.high = n1;
+					*rp = rr.ll;
+				}
+			} else {
+				u32 m1, m0;
+				/* Normalize.  */
 
-              b = SI_TYPE_SIZE - bm;
+				b = SI_TYPE_SIZE - bm;
 
-              d1 = (d1 << bm) | (d0 >> b);
-              d0 = d0 << bm;
-              n2 = n1 >> b;
-              n1 = (n1 << bm) | (n0 >> b);
-              n0 = n0 << bm;
+				d1 = (d1 << bm) | (d0 >> b);
+				d0 = d0 << bm;
+				n2 = n1 >> b;
+				n1 = (n1 << bm) | (n0 >> b);
+				n0 = n0 << bm;
 
-              udiv_qrnnd (q0, n1, n2, n1, d1);
-              umul_ppmm (m1, m0, q0, d0);
+				udiv_qrnnd(q0, n1, n2, n1, d1);
+				umul_ppmm(m1, m0, q0, d0);
 
-              if (m1 > n1 || (m1 == n1 && m0 > n0))
-                {
-                  q0--;
-                  sub_ddmmss (m1, m0, m1, m0, d1, d0);
-                }
+				if (m1 > n1 || (m1 == n1 && m0 > n0)) {
+					q0--;
+					sub_ddmmss(m1, m0, m1, m0, d1, d0);
+				}
 
-              q1 = 0;
+				q1 = 0;
 
-              /* Remainder in (n1n0 - m1m0) >> bm.  */
-              if (rp != 0)
-                {
-                  sub_ddmmss (n1, n0, n1, n0, m1, m0);
-                  rr.s.low = (n1 << b) | (n0 >> bm);
-                  rr.s.high = n1 >> bm;
-                  *rp = rr.ll;
-                }
-            }
-        }
-    }
+				/* Remainder in (n1n0 - m1m0) >> bm.  */
+				if (rp != 0) {
+					sub_ddmmss(n1, n0, n1, n0, m1, m0);
+					rr.s.low = (n1 << b) | (n0 >> bm);
+					rr.s.high = n1 >> bm;
+					*rp = rr.ll;
+				}
+			}
+		}
+	}
 
-  ww.s.low = q0;
-  ww.s.high = q1;
-  return ww.ll;
+	ww.s.low = q0;
+	ww.s.high = q1;
+	return ww.ll;
 }
 
-UDItype
-__udivdi3 (UDItype n, UDItype d)
+u64 __udivdi3(u64 n, u64 d)
 {
-  return __udivmoddi4 (n, d, (UDItype *) 0);
+	return __udivmoddi4(n, d, (u64 *) 0);
 }
 
-UDItype
-__umoddi3 (UDItype u, UDItype v)
+u64 __umoddi3(u64 u, u64 v)
 {
-  UDItype w;
+	u64 w;
 
-  (void) __udivmoddi4 (u ,v, &w);
+	(void)__udivmoddi4(u, v, &w);
 
-  return w;
+	return w;
 }
-
diff --git a/arch/arm/mach-aaec2000/Kconfig b/arch/arm/mach-aaec2000/Kconfig
new file mode 100644
index 0000000..5e4bef9
--- /dev/null
+++ b/arch/arm/mach-aaec2000/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_AAEC2000
+
+menu "Agilent AAEC-2000 Implementations"
+
+config MACH_AAED2000
+	bool "Agilent AAED-2000 Development Platform"
+	select CPU_ARM920T
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile
new file mode 100644
index 0000000..20ec838
--- /dev/null
+++ b/arch/arm/mach-aaec2000/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support (must be linked before board specific support)
+obj-y += core.o
+
+# Specific board support
+obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
new file mode 100644
index 0000000..5417ca3
--- /dev/null
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -0,0 +1,48 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/aaed2000.c
+ *
+ *  Support for the Agilent AAED-2000 Development Platform.
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "core.h"
+
+static void __init aaed2000_init_irq(void)
+{
+	aaec2000_init_irq();
+}
+
+static void __init aaed2000_map_io(void)
+{
+	aaec2000_map_io();
+}
+
+MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
+	MAINTAINER("Nicolas Bellido Y Ortega")
+	BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
+	MAPIO(aaed2000_map_io)
+	INITIRQ(aaed2000_init_irq)
+	.timer		= &aaec2000_timer,
+MACHINE_END
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
new file mode 100644
index 0000000..fc145b3
--- /dev/null
+++ b/arch/arm/mach-aaec2000/core.c
@@ -0,0 +1,157 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/core.c
+ *
+ *  Code common to all AAEC-2000 machines
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/signal.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+/*
+ * Common I/O mapping:
+ *
+ * Static virtual address mappings are as follow:
+ *
+ * 0xf8000000-0xf8001ffff: Devices connected to APB bus
+ * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
+ *
+ * Below 0xe8000000 is reserved for vm allocation.
+ *
+ * The machine specific code must provide the extra mapping beside the
+ * default mapping provided here.
+ */
+static struct map_desc standard_io_desc[] __initdata = {
+ /* virtual         physical       length           type */
+  { VIO_APB_BASE,   PIO_APB_BASE,  IO_APB_LENGTH,   MT_DEVICE },
+  { VIO_AHB_BASE,   PIO_AHB_BASE,  IO_AHB_LENGTH,   MT_DEVICE }
+};
+
+void __init aaec2000_map_io(void)
+{
+	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+/*
+ * Interrupt handling routines
+ */
+static void aaec2000_int_ack(unsigned int irq)
+{
+	IRQ_INTSR = 1 << irq;
+}
+
+static void aaec2000_int_mask(unsigned int irq)
+{
+	IRQ_INTENC |= (1 << irq);
+}
+
+static void aaec2000_int_unmask(unsigned int irq)
+{
+	IRQ_INTENS |= (1 << irq);
+}
+
+static struct irqchip aaec2000_irq_chip = {
+	.ack	= aaec2000_int_ack,
+	.mask	= aaec2000_int_mask,
+	.unmask	= aaec2000_int_unmask,
+};
+
+void __init aaec2000_init_irq(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_handler(i, do_level_IRQ);
+		set_irq_chip(i, &aaec2000_irq_chip);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	/* Disable all interrupts */
+	IRQ_INTENC = 0xffffffff;
+
+	/* Clear any pending interrupts */
+	IRQ_INTSR = IRQ_INTSR;
+}
+
+/*
+ * Time keeping
+ */
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long aaec2000_gettimeoffset(void)
+{
+	unsigned long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* Now, convert them to usec */
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
+
+	return usec;
+}
+
+/* We enter here with IRQs enabled */
+static irqreturn_t
+aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* TODO: Check timer accuracy */
+	write_seqlock(&xtime_lock);
+
+	timer_tick(regs);
+	TIMER1_CLEAR = 1;
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction aaec2000_timer_irq = {
+	.name		= "AAEC-2000 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= aaec2000_timer_interrupt
+};
+
+static void __init aaec2000_timer_init(void)
+{
+	/* Disable timer 1 */
+	TIMER1_CTRL = 0;
+
+	/* We have somehow to generate a 100Hz clock.
+	 * We then use the 508KHz timer in periodic mode.
+	 */
+	TIMER1_LOAD = LATCH;
+	TIMER1_CLEAR = 1; /* Clear interrupt */
+
+	setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
+
+	TIMER1_CTRL = TIMER_CTRL_ENABLE |
+	                TIMER_CTRL_PERIODIC |
+	                TIMER_CTRL_CLKSEL_508K;
+}
+
+struct sys_timer aaec2000_timer = {
+	.init		= aaec2000_timer_init,
+	.offset		= aaec2000_gettimeoffset,
+};
+
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
new file mode 100644
index 0000000..91893d8
--- /dev/null
+++ b/arch/arm/mach-aaec2000/core.h
@@ -0,0 +1,16 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/core.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+struct sys_timer;
+
+extern struct sys_timer aaec2000_timer;
+extern void __init aaec2000_map_io(void);
+extern void __init aaec2000_init_irq(void);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index d302f04..bd1e5e3 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -227,7 +227,6 @@
 	 * primary CPU
 	 */
 	if (hard_smp_processor_id() == 0) {
-		nmi_tick();
 		timer_tick(regs);
 #ifdef CONFIG_SMP
 		smp_send_timer();
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 4f3c3d5c..fc05555 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -162,12 +162,13 @@
 static unsigned ticks_per_jiffy;
 static unsigned ticks_per_usec;
 static unsigned next_jiffy_time;
+static volatile unsigned long *missing_jiffy_timer_csr;
 
 unsigned long ixp2000_gettimeoffset (void)
 {
  	unsigned long offset;
 
-	offset = next_jiffy_time - *IXP2000_T4_CSR;
+	offset = next_jiffy_time - *missing_jiffy_timer_csr;
 
 	return offset / ticks_per_usec;
 }
@@ -179,7 +180,7 @@
 	/* clear timer 1 */
 	ixp2000_reg_write(IXP2000_T1_CLR, 1);
 	
-	while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
+	while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
 		timer_tick(regs);
 		next_jiffy_time -= ticks_per_jiffy;
 	}
@@ -197,20 +198,37 @@
 
 void __init ixp2000_init_time(unsigned long tick_rate)
 {
-	ixp2000_reg_write(IXP2000_T1_CLR, 0);
-	ixp2000_reg_write(IXP2000_T4_CLR, 0);
-
 	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
 	ticks_per_usec = tick_rate / 1000000;
 
+	/*
+	 * We use timer 1 as our timer interrupt.
+	 */
+	ixp2000_reg_write(IXP2000_T1_CLR, 0);
 	ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
 	ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
 
 	/*
-	 * We use T4 as a monotonic counter to track missed jiffies
+	 * We use a second timer as a monotonic counter for tracking
+	 * missed jiffies.  The IXP2000 has four timers, but if we're
+	 * on an A-step IXP2800, timer 2 and 3 don't work, so on those
+	 * chips we use timer 4.  Timer 4 is the only timer that can
+	 * be used for the watchdog, so we use timer 2 if we're on a
+	 * non-buggy chip.
 	 */
-	ixp2000_reg_write(IXP2000_T4_CLD, -1);
-	ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+	if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+		printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
+
+		ixp2000_reg_write(IXP2000_T4_CLR, 0);
+		ixp2000_reg_write(IXP2000_T4_CLD, -1);
+		ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+		missing_jiffy_timer_csr = IXP2000_T4_CSR;
+	} else {
+		ixp2000_reg_write(IXP2000_T2_CLR, 0);
+		ixp2000_reg_write(IXP2000_T2_CLD, -1);
+		ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
+		missing_jiffy_timer_csr = IXP2000_T2_CSR;
+	}
  	next_jiffy_time = 0xffffffff;
 
 	/* register for interrupt */
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
index 5d60883..ba81e70 100644
--- a/arch/arm/mach-versatile/Makefile
+++ b/arch/arm/mach-versatile/Makefile
@@ -5,3 +5,4 @@
 obj-y					:= core.o clock.o
 obj-$(CONFIG_ARCH_VERSATILE_PB)		+= versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)		+= versatile_ab.o
+obj-$(CONFIG_PCI)			+= pci.o
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 302c2a7..6a7cbea 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -196,11 +196,15 @@
 #ifdef CONFIG_DEBUG_LL
  { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K,      MT_DEVICE },
 #endif
-#ifdef FIXME
- { PCI_MEMORY_VADDR,		     PHYS_PCI_MEM_BASE,    SZ_16M,     MT_DEVICE },
- { PCI_CONFIG_VADDR,		     PHYS_PCI_CONFIG_BASE, SZ_16M,     MT_DEVICE },
- { PCI_V3_VADDR,		     PHYS_PCI_V3_BASE,     SZ_512K,    MT_DEVICE },
- { PCI_IO_VADDR,		     PHYS_PCI_IO_BASE,     SZ_64K,     MT_DEVICE },
+#ifdef CONFIG_PCI
+ { IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
+ { VERSATILE_PCI_VIRT_BASE,          VERSATILE_PCI_BASE,   VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
+ { VERSATILE_PCI_CFG_VIRT_BASE,      VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
+#if 0
+ { VERSATILE_PCI_VIRT_MEM_BASE0,     VERSATILE_PCI_MEM_BASE0, SZ_16M,  MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE1,     VERSATILE_PCI_MEM_BASE1, SZ_16M,  MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE2,     VERSATILE_PCI_MEM_BASE2, SZ_16M,  MT_DEVICE },
+#endif
 #endif
 };
 
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
new file mode 100644
index 0000000..d1565e8
--- /dev/null
+++ b/arch/arm/mach-versatile/pci.c
@@ -0,0 +1,360 @@
+/*
+ *  linux/arch/arm/mach-versatile/pci.c
+ *
+ * (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
+ * You can redistribute and/or modify this software under the terms of version 2
+ * of the GNU General Public License as published by the Free Software Foundation.
+ * THIS SOFTWARE IS PROVIDED "AS IS" 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.
+ * Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
+ *
+ * ARM Versatile PCI driver.
+ *
+ * 14/04/2005 Initial version, colin.king@philips.com
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * these spaces are mapped using the following base registers:
+ *
+ * Usage Local Bus Memory         Base/Map registers used
+ *
+ * Mem   50000000 - 5FFFFFFF      LB_BASE0/LB_MAP0,  non prefetch
+ * Mem   60000000 - 6FFFFFFF      LB_BASE1/LB_MAP1,  prefetch
+ * IO    44000000 - 4FFFFFFF      LB_BASE2/LB_MAP2,  IO
+ * Cfg   42000000 - 42FFFFFF	  PCI config
+ *
+ */
+#define SYS_PCICTL			IO_ADDRESS(VERSATILE_SYS_PCICTL)
+#define PCI_IMAP0			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
+#define PCI_IMAP1			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
+#define PCI_IMAP2			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
+#define PCI_SMAP0			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
+#define PCI_SMAP1			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
+#define PCI_SMAP2			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SELFID			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
+
+#define DEVICE_ID_OFFSET		0x00
+#define CSR_OFFSET			0x04
+#define CLASS_ID_OFFSET			0x08
+
+#define VP_PCI_DEVICE_ID		0x030010ee
+#define VP_PCI_CLASS_ID			0x0b400000
+
+static unsigned long pci_slot_ignore = 0;
+
+static int __init versatile_pci_slot_ignore(char *str)
+{
+	int retval;
+	int slot;
+
+	while ((retval = get_option(&str,&slot))) {
+		if ((slot < 0) || (slot > 31)) {
+			printk("Illegal slot value: %d\n",slot);
+		} else {
+			pci_slot_ignore |= (1 << slot);
+		}
+	}
+	return 1;
+}
+
+__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
+
+
+static unsigned long __pci_addr(struct pci_bus *bus,
+				unsigned int devfn, int offset)
+{
+	unsigned int busnr = bus->number;
+
+	/*
+	 * Trap out illegal values
+	 */
+	if (offset > 255)
+		BUG();
+	if (busnr > 255)
+		BUG();
+	if (devfn > 255)
+		BUG();
+
+	return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
+		(PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
+}
+
+static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+				 int size, u32 *val)
+{
+	unsigned long addr = __pci_addr(bus, devfn, where);
+	u32 v;
+	int slot = PCI_SLOT(devfn);
+
+	if (pci_slot_ignore & (1 << slot)) {
+		/* Ignore this slot */
+		switch (size) {
+		case 1:
+			v = 0xff;
+			break;
+		case 2:
+			v = 0xffff;
+			break;
+		default:
+			v = 0xffffffff;
+		}
+	} else {
+		switch (size) {
+		case 1:
+			addr &= ~3;
+			v = __raw_readb(addr);
+			break;
+
+		case 2:
+			v = __raw_readl(addr & ~3);
+			if (addr & 2) v >>= 16;
+ 			v &= 0xffff;
+			break;
+
+		default:
+			addr &= ~3;
+			v = __raw_readl(addr);
+			break;
+		}
+	}
+
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+				  int size, u32 val)
+{
+	unsigned long addr = __pci_addr(bus, devfn, where);
+	int slot = PCI_SLOT(devfn);
+
+	if (pci_slot_ignore & (1 << slot)) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	switch (size) {
+	case 1:
+		__raw_writeb((u8)val, addr);
+		break;
+
+	case 2:
+		__raw_writew((u16)val, addr);
+		break;
+
+	case 4:
+		__raw_writel(val, addr);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_versatile_ops = {
+	.read	= versatile_read_config,
+	.write	= versatile_write_config,
+};
+
+static struct resource io_mem = {
+	.name	= "PCI I/O space",
+	.start	= VERSATILE_PCI_MEM_BASE0,
+	.end	= VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource non_mem = {
+	.name	= "PCI non-prefetchable",
+	.start	= VERSATILE_PCI_MEM_BASE1,
+	.end	= VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource pre_mem = {
+	.name	= "PCI prefetchable",
+	.start	= VERSATILE_PCI_MEM_BASE2,
+	.end	= VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
+	.flags	= IORESOURCE_MEM | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_versatile_setup_resources(struct resource **resource)
+{
+	int ret = 0;
+
+	ret = request_resource(&iomem_resource, &io_mem);
+	if (ret) {
+		printk(KERN_ERR "PCI: unable to allocate I/O "
+		       "memory region (%d)\n", ret);
+		goto out;
+	}
+	ret = request_resource(&iomem_resource, &non_mem);
+	if (ret) {
+		printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
+		       "memory region (%d)\n", ret);
+		goto release_io_mem;
+	}
+	ret = request_resource(&iomem_resource, &pre_mem);
+	if (ret) {
+		printk(KERN_ERR "PCI: unable to allocate prefetchable "
+		       "memory region (%d)\n", ret);
+		goto release_non_mem;
+	}
+
+	/*
+	 * bus->resource[0] is the IO resource for this bus
+	 * bus->resource[1] is the mem resource for this bus
+	 * bus->resource[2] is the prefetch mem resource for this bus
+	 */
+	resource[0] = &io_mem;
+	resource[1] = &non_mem;
+	resource[2] = &pre_mem;
+
+	goto out;
+
+ release_non_mem:
+	release_resource(&non_mem);
+ release_io_mem:
+	release_resource(&io_mem);
+ out:
+	return ret;
+}
+
+int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
+{
+	int ret = 0;
+        int i;
+        int myslot = -1;
+	unsigned long val;
+
+	if (nr == 0) {
+		sys->mem_offset = 0;
+		ret = pci_versatile_setup_resources(sys->resource);
+		if (ret < 0) {
+			printk("pci_versatile_setup: resources... oops?\n");
+			goto out;
+		}
+	} else {
+		printk("pci_versatile_setup: resources... nr == 0??\n");
+		goto out;
+	}
+
+	__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
+	__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
+	__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
+
+	__raw_writel(1, SYS_PCICTL);
+
+	val = __raw_readl(SYS_PCICTL);
+	if (!(val & 1)) {
+		printk("Not plugged into PCI backplane!\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	/*
+	 *  We need to discover the PCI core first to configure itself
+	 *  before the main PCI probing is performed
+	 */
+	for (i=0; i<32; i++) {
+		if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
+		    (__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
+			myslot = i;
+
+			__raw_writel(myslot, PCI_SELFID);
+			val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+			val |= (1<<2);
+			__raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+			break;
+		}
+	}
+
+	if (myslot == -1) {
+		printk("Cannot find PCI core!\n");
+		ret = -EIO;
+	} else {
+		printk("PCI core found (slot %d)\n",myslot);
+		/* Do not to map Versatile FPGA PCI device
+		   into memory space as we are short of
+		   mappable memory */
+		pci_slot_ignore |= (1 << myslot);
+		ret = 1;
+	}
+
+ out:
+	return ret;
+}
+
+
+struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
+}
+
+/*
+ * V3_LB_BASE? - local bus address
+ * V3_LB_MAP?  - pci bus address
+ */
+void __init pci_versatile_preinit(void)
+{
+}
+
+void __init pci_versatile_postinit(void)
+{
+}
+
+
+/*
+ * map the specified device/slot/pin to an IRQ.   Different backplanes may need to modify this.
+ */
+static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+	int devslot = PCI_SLOT(dev->devfn);
+
+	/* slot,  pin,  irq
+	    24	  1	27
+	    25    1	28	untested
+	    26	  1	29
+	    27    1	30	untested
+	*/
+
+	irq = 27 + ((slot + pin + 2) % 3);	/* Fudged */
+
+	printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
+
+	return irq;
+}
+
+static struct hw_pci versatile_pci __initdata = {
+	.swizzle		= NULL,
+	.map_irq		= versatile_map_irq,
+	.nr_controllers		= 1,
+	.setup			= pci_versatile_setup,
+	.scan			= pci_versatile_scan_bus,
+	.preinit		= pci_versatile_preinit,
+	.postinit		= pci_versatile_postinit,
+};
+
+static int __init versatile_pci_init(void)
+{
+	pci_common_init(&versatile_pci);
+	return 0;
+}
+
+subsys_initcall(versatile_pci_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 3fefb43..95606b4 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -62,7 +62,7 @@
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
+	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
 	default y if ARCH_S3C2410
 	select CPU_32v4
 	select CPU_ABRT_EV4T
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index a8c0023..27d0415 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -30,8 +30,6 @@
 
 static DEFINE_SPINLOCK(v6_lock);
 
-#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
-
 /*
  * Copy the user page.  No aliasing to deal with so we can just
  * attack the kernel's existing mapping of these pages.
@@ -55,7 +53,7 @@
  */
 void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
-	unsigned int offset = DCACHE_COLOUR(vaddr);
+	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long from, to;
 
 	/*
@@ -95,7 +93,7 @@
  */
 void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
-	unsigned int offset = DCACHE_COLOUR(vaddr);
+	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long to = to_address + (offset << PAGE_SHIFT);
 
 	/*
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 01967dde..be4ab3d 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -77,9 +77,8 @@
 }
 
 static void
-make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
+make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 {
-	struct address_space *mapping = page_mapping(page);
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
@@ -87,9 +86,6 @@
 	pgoff_t pgoff;
 	int aliases = 0;
 
-	if (!mapping)
-		return;
-
 	pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
 
 	/*
@@ -115,9 +111,11 @@
 	if (aliases)
 		adjust_pte(vma, addr);
 	else
-		flush_cache_page(vma, addr, page_to_pfn(page));
+		flush_cache_page(vma, addr, pfn);
 }
 
+void __flush_dcache_page(struct address_space *mapping, struct page *page);
+
 /*
  * Take care of architecture specific things when placing a new PTE into
  * a page table, or changing an existing PTE.  Basically, there are two
@@ -134,29 +132,22 @@
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 {
 	unsigned long pfn = pte_pfn(pte);
+	struct address_space *mapping;
 	struct page *page;
 
 	if (!pfn_valid(pfn))
 		return;
+
 	page = pfn_to_page(pfn);
-	if (page_mapping(page)) {
+	mapping = page_mapping(page);
+	if (mapping) {
 		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
 
-		if (dirty) {
-			/*
-			 * This is our first userspace mapping of this page.
-			 * Ensure that the physical page is coherent with
-			 * the kernel mapping.
-			 *
-			 * FIXME: only need to do this on VIVT and aliasing
-			 *        VIPT cache architectures.  We can do that
-			 *	  by choosing whether to set this bit...
-			 */
-			__cpuc_flush_dcache_page(page_address(page));
-		}
+		if (dirty)
+			__flush_dcache_page(mapping, page);
 
 		if (cache_is_vivt())
-			make_coherent(vma, addr, page, dirty);
+			make_coherent(mapping, vma, addr, pfn);
 	}
 }
 
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 4085ed9..191788f 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -37,13 +37,8 @@
 #define flush_pfn_alias(pfn,vaddr)	do { } while (0)
 #endif
 
-static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
 {
-	struct mm_struct *mm = current->active_mm;
-	struct vm_area_struct *mpnt;
-	struct prio_tree_iter iter;
-	pgoff_t pgoff;
-
 	/*
 	 * Writeback any data associated with the kernel mapping of this
 	 * page.  This ensures that data in the physical page is mutually
@@ -52,24 +47,21 @@
 	__cpuc_flush_dcache_page(page_address(page));
 
 	/*
-	 * If there's no mapping pointer here, then this page isn't
-	 * visible to userspace yet, so there are no cache lines
-	 * associated with any other aliases.
-	 */
-	if (!mapping)
-		return;
-
-	/*
-	 * This is a page cache page.  If we have a VIPT cache, we
-	 * only need to do one flush - which would be at the relevant
+	 * If this is a page cache page, and we have an aliasing VIPT cache,
+	 * we only need to do one flush - which would be at the relevant
 	 * userspace colour, which is congruent with page->index.
 	 */
-	if (cache_is_vipt()) {
-		if (cache_is_vipt_aliasing())
-			flush_pfn_alias(page_to_pfn(page),
-					page->index << PAGE_CACHE_SHIFT);
-		return;
-	}
+	if (mapping && cache_is_vipt_aliasing())
+		flush_pfn_alias(page_to_pfn(page),
+				page->index << PAGE_CACHE_SHIFT);
+}
+
+static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
+{
+	struct mm_struct *mm = current->active_mm;
+	struct vm_area_struct *mpnt;
+	struct prio_tree_iter iter;
+	pgoff_t pgoff;
 
 	/*
 	 * There are possible user space mappings of this page:
@@ -116,12 +108,12 @@
 {
 	struct address_space *mapping = page_mapping(page);
 
-	if (cache_is_vipt_nonaliasing())
-		return;
-
 	if (mapping && !mapping_mapped(mapping))
 		set_bit(PG_dcache_dirty, &page->flags);
-	else
+	else {
 		__flush_dcache_page(mapping, page);
+		if (mapping && cache_is_vivt())
+			__flush_dcache_aliases(mapping, page);
+	}
 }
 EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 00bb8fd..7110e54 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -170,3 +170,50 @@
 	vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
 EXPORT_SYMBOL(__iounmap);
+
+#ifdef __io
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return __io(port);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif
+
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len   = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+		return ioremap_nocache(start, len);
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	if ((unsigned long)addr >= VMALLOC_START &&
+	    (unsigned long)addr < VMALLOC_END)
+		iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+#endif
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 3441646..8316426 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -423,6 +423,9 @@
 	tbl->it_largehint = tbl->it_halfpoint;
 	spin_lock_init(&tbl->it_lock);
 
+	/* Clear the hardware table in case firmware left allocations in it */
+	ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+
 	if (!welcomed) {
 		printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
 		       novmerge ? "disabled" : "enabled");
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index fbad349..4203bd0 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -375,7 +375,7 @@
 	 * cpus are assumed to be secondary threads.
 	 */
 	if (system_state < SYSTEM_RUNNING &&
-	    cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
+	    cpu_has_feature(CPU_FTR_SMT) &&
 	    !smt_enabled_at_boot && nr % 2 != 0)
 		return 0;
 
@@ -419,8 +419,8 @@
 #endif
 
 	/* Mark threads which are still spinning in hold loops. */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-		for_each_present_cpu(i) {
+	if (cpu_has_feature(CPU_FTR_SMT)) {
+		for_each_present_cpu(i) { 
 			if (i % 2 == 0)
 				/*
 				 * Even-numbered logical cpus correspond to
@@ -428,8 +428,9 @@
 				 */
 				cpu_set(i, of_spin_map);
 		}
-	else
+	} else {
 		of_spin_map = cpu_present_map;
+	}
 
 	cpu_clear(boot_cpuid, of_spin_map);
 
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index ff65dc3..b0c3b82 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -440,7 +440,7 @@
 		goto error;
 	}
 
-	printk(KERN_ERR "RTAS daemon started\n");
+	printk(KERN_INFO "RTAS daemon started\n");
 
 	DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
 
@@ -485,7 +485,7 @@
 	/* No RTAS, only warn if we are on a pSeries box  */
 	if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
 		if (systemcfg->platform & PLATFORM_PSERIES)
-			printk(KERN_ERR "rtasd: no event-scan on system\n");
+			printk(KERN_INFO "rtasd: no event-scan on system\n");
 		return 1;
 	}
 
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index ab659d3..4e98c21 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -192,7 +192,12 @@
 
 static int __init ixp2000_wdt_init(void)
 {
-	wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;;
+	if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+		printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+		return -EIO;
+	}
+
+	wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
 
 	return misc_register(&ixp2000_wdt_miscdev);
 }
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index fbd9ff7..e3c9588 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -765,8 +765,6 @@
 
 static void fcp_scsi_done (Scsi_Cmnd *SCpnt)
 {
-	unsigned long flags;
-
 	if (FCP_CMND(SCpnt)->done)
 		FCP_CMND(SCpnt)->done(SCpnt);
 }
@@ -907,8 +905,6 @@
 	 */
 
 	if (++fc->abort_count < (fc->can_queue >> 1)) {
-		unsigned long flags;
-
 		SCpnt->result = DID_ABORT;
 		fcmd->done(SCpnt);
 		printk("FC: soft abort\n");
@@ -931,6 +927,7 @@
 
 int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
 {
+	unsigned long flags;
 	fcp_cmd *cmd;
 	fcp_cmnd *fcmd;
 	fc_channel *fc = FC_SCMND(SCpnt);
@@ -1028,6 +1025,7 @@
 
 int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
 {
+	unsigned long flags;
 	int rc;
 
 	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index c4eaaad..5f526dd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -941,7 +941,7 @@
 	 */
 	cmd->scsi_done = scsi_done;
 
-	ahd_lock(ahd, &flags);
+	ahd_midlayer_entrypoint_lock(ahd, &flags);
 
 	/*
 	 * Close the race of a command that was in the process of
@@ -955,7 +955,7 @@
 		ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		ahd_schedule_completeq(ahd);
-		ahd_unlock(ahd, &flags);
+		ahd_midlayer_entrypoint_unlock(ahd, &flags);
 		return (0);
 	}
 	dev = ahd_linux_get_device(ahd, cmd->device->channel,
@@ -965,7 +965,7 @@
 		ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		ahd_schedule_completeq(ahd);
-		ahd_unlock(ahd, &flags);
+		ahd_midlayer_entrypoint_unlock(ahd, &flags);
 		printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
 		       ahd_name(ahd));
 		return (0);
@@ -979,7 +979,7 @@
 		dev->flags |= AHD_DEV_ON_RUN_LIST;
 		ahd_linux_run_device_queues(ahd);
 	}
-	ahd_unlock(ahd, &flags);
+	ahd_midlayer_entrypoint_unlock(ahd, &flags);
 	return (0);
 }
 
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h
new file mode 100644
index 0000000..0e9b7e1
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/aaec2000.h
@@ -0,0 +1,151 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/aaec2000.h
+ *
+ *  AAEC-2000 registers definition
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_AAEC2000_H
+#define __ASM_ARCH_AAEC2000_H
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error You must include hardware.h not this file
+#endif /* __ASM_ARCH_HARDWARE_H */
+
+/* Interrupt controller */
+#define IRQ_BASE	__REG(0x80000500)
+#define IRQ_INTSR	__REG(0x80000500)	/* Int Status Register */
+#define IRQ_INTRSR	__REG(0x80000504)	/* Int Raw (unmasked) Status */
+#define IRQ_INTENS	__REG(0x80000508)	/* Int Enable Set */
+#define IRQ_INTENC	__REG(0x8000050c)	/* Int Enable Clear */
+
+/* UART 1 */
+#define UART1_BASE	__REG(0x80000600)
+#define UART1_DR	__REG(0x80000600) /* Data/FIFO Register */
+#define UART1_LCR	__REG(0x80000604) /* Link Control Register */
+#define UART1_BRCR	__REG(0x80000608) /* Baud Rate Control Register */
+#define UART1_CR	__REG(0x8000060c) /* Control Register */
+#define UART1_SR	__REG(0x80000610) /* Status Register */
+#define UART1_INT	__REG(0x80000614) /* Interrupt Status Register */
+#define UART1_INTM	__REG(0x80000618) /* Interrupt Mask Register */
+#define UART1_INTRES	__REG(0x8000061c) /* Int Result (masked status) Register */
+
+/* UART 2 */
+#define UART2_BASE	__REG(0x80000700)
+#define UART2_DR	__REG(0x80000700) /* Data/FIFO Register */
+#define UART2_LCR	__REG(0x80000704) /* Link Control Register */
+#define UART2_BRCR	__REG(0x80000708) /* Baud Rate Control Register */
+#define UART2_CR	__REG(0x8000070c) /* Control Register */
+#define UART2_SR	__REG(0x80000710) /* Status Register */
+#define UART2_INT	__REG(0x80000714) /* Interrupt Status Register */
+#define UART2_INTM	__REG(0x80000718) /* Interrupt Mask Register */
+#define UART2_INTRES	__REG(0x8000071c) /* Int Result (masked status) Register */
+
+/* UART 3 */
+#define UART3_BASE	__REG(0x80000800)
+#define UART3_DR	__REG(0x80000800) /* Data/FIFO Register */
+#define UART3_LCR	__REG(0x80000804) /* Link Control Register */
+#define UART3_BRCR	__REG(0x80000808) /* Baud Rate Control Register */
+#define UART3_CR	__REG(0x8000080c) /* Control Register */
+#define UART3_SR	__REG(0x80000810) /* Status Register */
+#define UART3_INT	__REG(0x80000814) /* Interrupt Status Register */
+#define UART3_INTM	__REG(0x80000818) /* Interrupt Mask Register */
+#define UART3_INTRES	__REG(0x8000081c) /* Int Result (masked status) Register */
+
+/* These are used in some places */
+#define _UART1_BASE __PREG(UART1_BASE)
+#define _UART2_BASE __PREG(UART2_BASE)
+#define _UART3_BASE __PREG(UART3_BASE)
+
+/* UART Registers Offsets */
+#define UART_DR		0x00
+#define UART_LCR	0x04
+#define UART_BRCR	0x08
+#define UART_CR		0x0c
+#define UART_SR		0x10
+#define UART_INT	0x14
+#define UART_INTM	0x18
+#define UART_INTRES	0x1c
+
+/* UART_LCR Bitmask */
+#define UART_LCR_BRK	(1 << 0) /* Send Break */
+#define UART_LCR_PEN	(1 << 1) /* Parity Enable */
+#define UART_LCR_EP	(1 << 2) /* Even/Odd Parity */
+#define UART_LCR_S2	(1 << 3) /* One/Two Stop bits */
+#define UART_LCR_FIFO	(1 << 4) /* FIFO Enable */
+#define UART_LCR_WL5	(0 << 5) /* Word Length - 5 bits */
+#define UART_LCR_WL6	(1 << 5) /* Word Length - 6 bits */
+#define UART_LCR_WL7	(1 << 6) /* Word Length - 7 bits */
+#define UART_LCR_WL8	(1 << 7) /* Word Length - 8 bits */
+
+/* UART_CR Bitmask */
+#define UART_CR_EN	(1 << 0) /* UART Enable */
+#define UART_CR_SIR	(1 << 1) /* IrDA SIR Enable */
+#define UART_CR_SIRLP	(1 << 2) /* Low Power IrDA Enable */
+#define UART_CR_RXP	(1 << 3) /* Receive Pin Polarity */
+#define UART_CR_TXP	(1 << 4) /* Transmit Pin Polarity */
+#define UART_CR_MXP	(1 << 5) /* Modem Pin Polarity */
+#define UART_CR_LOOP	(1 << 6) /* Loopback Mode */
+
+/* UART_SR Bitmask */
+#define UART_SR_CTS	(1 << 0) /* Clear To Send Status */
+#define UART_SR_DSR	(1 << 1) /* Data Set Ready Status */
+#define UART_SR_DCD	(1 << 2) /* Data Carrier Detect Status */
+#define UART_SR_TxBSY	(1 << 3) /* Transmitter Busy Status */
+#define UART_SR_RxFE	(1 << 4) /* Receive FIFO Empty Status */
+#define UART_SR_TxFF	(1 << 5) /* Transmit FIFO Full Status */
+#define UART_SR_RxFF	(1 << 6) /* Receive FIFO Full Status */
+#define UART_SR_TxFE	(1 << 7) /* Transmit FIFO Empty Status */
+
+/* UART_INT Bitmask */
+#define UART_INT_RIS	(1 << 0) /* Rx Interrupt */
+#define UART_INT_TIS	(1 << 1) /* Tx Interrupt */
+#define UART_INT_MIS	(1 << 2) /* Modem Interrupt */
+#define UART_INT_RTIS	(1 << 3) /* Receive Timeout Interrupt */
+
+/* Timer 1 */
+#define TIMER1_BASE	__REG(0x80000c00)
+#define TIMER1_LOAD	__REG(0x80000c00)	/* Timer 1 Load Register */
+#define TIMER1_VAL	__REG(0x80000c04)	/* Timer 1 Value Register */
+#define TIMER1_CTRL	__REG(0x80000c08)	/* Timer 1 Control Register */
+#define TIMER1_CLEAR	__REG(0x80000c0c)	/* Timer 1 Clear Register */
+
+/* Timer 2 */
+#define TIMER2_BASE	__REG(0x80000d00)
+#define TIMER2_LOAD	__REG(0x80000d00)	/* Timer 2 Load Register */
+#define TIMER2_VAL	__REG(0x80000d04)	/* Timer 2 Value Register */
+#define TIMER2_CTRL	__REG(0x80000d08)	/* Timer 2 Control Register */
+#define TIMER2_CLEAR	__REG(0x80000d0c)	/* Timer 2 Clear Register */
+
+/* Timer 3 */
+#define TIMER3_BASE	__REG(0x80000e00)
+#define TIMER3_LOAD	__REG(0x80000e00)	/* Timer 3 Load Register */
+#define TIMER3_VAL	__REG(0x80000e04)	/* Timer 3 Value Register */
+#define TIMER3_CTRL	__REG(0x80000e08)	/* Timer 3 Control Register */
+#define TIMER3_CLEAR	__REG(0x80000e0c)	/* Timer 3 Clear Register */
+
+/* Timer Control register bits */
+#define TIMER_CTRL_ENABLE	(1 << 7) /* Enable (Start° Timer */
+#define TIMER_CTRL_PERIODIC	(1 << 6) /* Periodic Running Mode */
+#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
+#define TIMER_CTRL_CLKSEL_508K	(1 << 3) /* 508KHz Clock select (Timer 1, 2) */
+#define TIMER_CTRL_CLKSEL_2K	(0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/
+
+/* Power and State Control */
+#define POWER_BASE	__REG(0x80000400)
+#define POWER_PWRSR	__REG(0x80000400) /* Power Status Register */
+#define POWER_PWRCNT	__REG(0x80000404) /* Power/Clock control */
+#define POWER_HALT	__REG(0x80000408) /* Power Idle Mode */
+#define POWER_STDBY	__REG(0x8000040c) /* Power Standby Mode */
+#define POWER_BLEOI	__REG(0x80000410) /* Battery Low End of Interrupt */
+#define POWER_MCEOI	__REG(0x80000414) /* Media Changed EoI */
+#define POWER_TEOI	__REG(0x80000418) /* Tick EoI */
+#define POWER_STFCLR	__REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
+#define POWER_CLKSET	__REG(0x80000420) /* Clock Speed Control */
+
+#endif /* __ARM_ARCH_AAEC2000_H */
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
new file mode 100644
index 0000000..e4f1fa5
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/debug-macro.S
@@ -0,0 +1,36 @@
+/*  linux/include/asm-arm/arch-aaec2000/debug-macro.S
+ *
+ *  Debugging macro include header
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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.
+ */
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x80000000		@ physical
+		movne	\rx, #io_p2v(0x80000000)	@ virtual
+		orr	\rx, \rx, #0x00000800
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x10]
+		tst	\rd, #(1 << 7)
+		beq	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+#if 0
+1001:		ldr	\rd, [\rx, #0x10]
+		tst	\rd, #(1 << 5)
+		beq	1001b
+#endif
+		.endm
diff --git a/include/asm-arm/arch-aaec2000/dma.h b/include/asm-arm/arch-aaec2000/dma.h
new file mode 100644
index 0000000..28c890b
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/dma.h
@@ -0,0 +1,17 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/dma.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS         0xffffffff
+#define MAX_DMA_CHANNELS        0
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
new file mode 100644
index 0000000..df31313
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -0,0 +1,33 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/entry-macro.S
+ *
+ *  Low-level IRQ helper for aaec-2000 based platforms
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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.
+ *
+ */
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov	r4, #0xf8000000
+		add	r4, r4, #0x00000500
+		mov	\base, r4
+		ldr	\irqstat, [\base, #0]
+		cmp	\irqstat, #0
+		bne	1001f
+		ldr	\irqnr, =NR_IRQS+1
+		b       1003f
+1001:		mov	\irqnr, #0
+1002:		ands	\tmp, \irqstat, #1
+		mov	\irqstat, \irqstat, LSR #1
+		add	\irqnr, \irqnr, #1
+		beq	1002b
+		sub	\irqnr, \irqnr, #1
+1003:
+		.endm
diff --git a/include/asm-arm/arch-aaec2000/hardware.h b/include/asm-arm/arch-aaec2000/hardware.h
new file mode 100644
index 0000000..4c37219e
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/hardware.h
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/hardware.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+/* The kernel is loaded at physical address 0xf8000000.
+ * We map the IO space a bit after
+ */
+#define PIO_APB_BASE	0x80000000
+#define VIO_APB_BASE	0xf8000000
+#define IO_APB_LENGTH	0x2000
+#define PIO_AHB_BASE	0x80002000
+#define VIO_AHB_BASE	0xf8002000
+#define IO_AHB_LENGTH	0x2000
+
+#define VIO_BASE    VIO_APB_BASE
+#define PIO_BASE    PIO_APB_BASE
+
+#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
+#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
+
+#ifndef __ASSEMBLY__
+
+#include <asm/types.h>
+
+/* FIXME: Is it needed to optimize this a la pxa ?? */
+#define __REG(x)    (*((volatile u32 *)io_p2v(x)))
+#define __PREG(x)   (io_v2p((u32)&(x)))
+
+#else /* __ASSEMBLY__ */
+
+#define __REG(x)    io_p2v(x)
+#define __PREG(x)   io_v2p(x)
+
+#endif
+
+#include "aaec2000.h"
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-aaec2000/io.h b/include/asm-arm/arch-aaec2000/io.h
new file mode 100644
index 0000000..c58a8d1
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/io.h
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/io.h
+ *
+ *  Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+#define __mem_isa(a)		(a)
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/irqs.h b/include/asm-arm/arch-aaec2000/irqs.h
new file mode 100644
index 0000000..de25222
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/irqs.h
@@ -0,0 +1,46 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/irqs.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+
+#define INT_GPIOF0_FIQ	0  /* External GPIO Port F O Fast Interrupt Input */
+#define INT_BL_FIQ	1  /* Battery Low Fast Interrupt */
+#define INT_WE_FIQ	2  /* Watchdog Expired Fast Interrupt */
+#define INT_MV_FIQ	3  /* Media Changed Interrupt */
+#define INT_SC		4  /* Sound Codec Interrupt */
+#define INT_GPIO1	5  /* GPIO Port F Configurable Int 1 */
+#define INT_GPIO2	6  /* GPIO Port F Configurable Int 2 */
+#define INT_GPIO3	7  /* GPIO Port F Configurable Int 3 */
+#define INT_TMR1_OFL	8  /* Timer 1 Overflow Interrupt */
+#define INT_TMR2_OFL	9  /* Timer 2 Overflow Interrupt */
+#define INT_RTC_CM	10 /* RTC Compare Match Interrupt */
+#define INT_TICK	11 /* 64Hz Tick Interrupt */
+#define INT_UART1	12 /* UART1 Interrupt */
+#define INT_UART2	13 /* UART2 & Modem State Changed Interrupt */
+#define INT_LCD		14 /* LCD Interrupt */
+#define INT_SSI		15 /* SSI End of Transfer Interrupt */
+#define INT_UART3	16 /* UART3 Interrupt */
+#define INT_SCI		17 /* SCI Interrupt */
+#define INT_AAC		18 /* Advanced Audio Codec Interrupt */
+#define INT_MMC		19 /* MMC Interrupt */
+#define INT_USB		20 /* USB Interrupt */
+#define INT_DMA		21 /* DMA Interrupt */
+#define INT_TMR3_UOFL	22 /* Timer 3 Underflow Interrupt */
+#define INT_GPIO4	23 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO5	24 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO6	25 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO7	26 /* GPIO Port F Configurable Int 4 */
+#define INT_BMI		27 /* BMI Interrupt */
+
+#define NR_IRQS		(INT_BMI + 1)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
new file mode 100644
index 0000000..681b6a6
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -0,0 +1,73 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/memory.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <linux/config.h>
+
+#define PHYS_OFFSET	(0xf0000000UL)
+
+#define __virt_to_bus(x)	__virt_to_phys(x)
+#define __bus_to_virt(x)	__phys_to_virt(x)
+
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * The nodes are the followings:
+ *
+ *   node 0: 0xf000.0000 - 0xf3ff.ffff
+ *   node 1: 0xf400.0000 - 0xf7ff.ffff
+ *   node 2: 0xf800.0000 - 0xfbff.ffff
+ *   node 3: 0xfc00.0000 - 0xffff.ffff
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+	(((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) \
+	(((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr)  NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn)     NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ *  Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ *  and returns the index corresponding to the appropriate page in the
+ *  node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+        (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
+
+#define NODE_MAX_MEM_SHIFT	26
+#define NODE_MAX_MEM_SIZE	(1 << NODE_MAX_MEM_SHIFT)
+
+#else
+
+#define PFN_TO_NID(addr)	(0)
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-aaec2000/param.h b/include/asm-arm/arch-aaec2000/param.h
new file mode 100644
index 0000000..139936c
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/param.h
@@ -0,0 +1,15 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/param.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+#endif /* __ASM_ARCH_PARAM_H */
+
diff --git a/include/asm-arm/arch-aaec2000/system.h b/include/asm-arm/arch-aaec2000/system.h
new file mode 100644
index 0000000..08de97b
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/system.h
@@ -0,0 +1,24 @@
+/*
+ *  linux/include/asm-arm/arch-aaed2000/system.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	cpu_reset(0);
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-aaec2000/timex.h b/include/asm-arm/arch-aaec2000/timex.h
new file mode 100644
index 0000000..f5708b3
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/timex.h
@@ -0,0 +1,18 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/timex.h
+ *
+ *  AAEC-2000 Architecture timex specification
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#define CLOCK_TICK_RATE		508000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h
new file mode 100644
index 0000000..fff0c94
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/uncompress.h
@@ -0,0 +1,47 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/uncompress.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include "hardware.h"
+
+#define UART(x)         (*(volatile unsigned long *)(serial_port + (x)))
+
+static void putstr( const char *s )
+{
+	unsigned long serial_port;
+        do {
+		serial_port = _UART3_BASE;
+		if (UART(UART_CR) & UART_CR_EN) break;
+		serial_port = _UART1_BASE;
+		if (UART(UART_CR) & UART_CR_EN) break;
+		serial_port = _UART2_BASE;
+		if (UART(UART_CR) & UART_CR_EN) break;
+		return;
+	} while (0);
+
+	for (; *s; s++) {
+		/* wait for space in the UART's transmitter */
+		while ((UART(UART_SR) & UART_SR_TxFF));
+		/* send the character out. */
+		UART(UART_DR) = *s;
+		/* if a LF, also do CR... */
+		if (*s == 10) {
+			while ((UART(UART_SR) & UART_SR_TxFF));
+			UART(UART_DR) = 13;
+		}
+	}
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-aaec2000/vmalloc.h b/include/asm-arm/arch-aaec2000/vmalloc.h
new file mode 100644
index 0000000..ecb991e
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/vmalloc.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END		(PAGE_OFFSET + 0x10000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 6c56708..a1d9e18 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -363,6 +363,7 @@
 #define IXP2000_MIN_REV_MASK	      	0x0000000F
 #define IXP2000_PROD_ID_MASK		0xFFFFFFFF
 
+#define IXP2000_PRODUCT_ID		GLOBAL_REG(0x00)
 #define IXP2000_MISC_CONTROL		GLOBAL_REG(0x04)
 #define IXP2000_MSF_CLK_CNTRL  		GLOBAL_REG(0x08)
 #define IXP2000_RESET0      		GLOBAL_REG(0x0c)
diff --git a/include/asm-arm/arch-versatile/hardware.h b/include/asm-arm/arch-versatile/hardware.h
index d5fb4a2..41c1bee 100644
--- a/include/asm-arm/arch-versatile/hardware.h
+++ b/include/asm-arm/arch-versatile/hardware.h
@@ -25,19 +25,26 @@
 #include <asm/sizes.h>
 #include <asm/arch/platform.h>
 
-// FIXME = PCI settings need to be fixed!!!!!
-
 /*
- * Similar to above, but for PCI addresses (memory, IO, Config and the
- * V3 chip itself).  WARNING: this has to mirror definitions in platform.h
+ * PCI space virtual addresses
  */
-#define PCI_MEMORY_VADDR       0xe8000000
-#define PCI_CONFIG_VADDR       0xec000000
-#define PCI_V3_VADDR           0xed000000
-#define PCI_IO_VADDR           0xee000000
+#define VERSATILE_PCI_VIRT_BASE		0xe8000000
+#define VERSATILE_PCI_CFG_VIRT_BASE	0xe9000000
 
-#define PCIO_BASE		PCI_IO_VADDR
-#define PCIMEM_BASE		PCI_MEMORY_VADDR
+#if 0
+#define VERSATILE_PCI_VIRT_MEM_BASE0	0xf4000000
+#define VERSATILE_PCI_VIRT_MEM_BASE1	0xf5000000
+#define VERSATILE_PCI_VIRT_MEM_BASE2	0xf6000000
+
+#define PCIO_BASE			VERSATILE_PCI_VIRT_MEM_BASE0
+#define PCIMEM_BASE			VERSATILE_PCI_VIRT_MEM_BASE1
+#endif
+
+/* CIK guesswork */
+#define PCIBIOS_MIN_IO			0x44000000
+#define PCIBIOS_MIN_MEM			0x50000000
+
+#define pcibios_assign_all_busses()     1
 
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x)		(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h
index dbb7158..9f895bf 100644
--- a/include/asm-arm/arch-versatile/io.h
+++ b/include/asm-arm/arch-versatile/io.h
@@ -20,7 +20,7 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h
index a71093e..cbdd9fb 100644
--- a/include/asm-arm/arch-versatile/platform.h
+++ b/include/asm-arm/arch-versatile/platform.h
@@ -76,7 +76,7 @@
 #define VERSATILE_SYS_NVFLAGSSET_OFFSET       0x38
 #define VERSATILE_SYS_NVFLAGSCLR_OFFSET       0x3C
 #define VERSATILE_SYS_RESETCTL_OFFSET         0x40
-#define VERSATILE_SYS_PICCTL_OFFSET           0x44
+#define VERSATILE_SYS_PCICTL_OFFSET           0x44
 #define VERSATILE_SYS_MCI_OFFSET              0x48
 #define VERSATILE_SYS_FLASH_OFFSET            0x4C
 #define VERSATILE_SYS_CLCD_OFFSET             0x50
@@ -114,7 +114,7 @@
 #define VERSATILE_SYS_NVFLAGSSET              (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET)
 #define VERSATILE_SYS_NVFLAGSCLR              (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET)
 #define VERSATILE_SYS_RESETCTL                (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET)
-#define VERSATILE_SYS_PICCTL                  (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET)
+#define VERSATILE_SYS_PCICTL                  (VERSATILE_SYS_BASE + VERSATILE_SYS_PCICTL_OFFSET)
 #define VERSATILE_SYS_MCI                     (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET)
 #define VERSATILE_SYS_FLASH                   (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET)
 #define VERSATILE_SYS_CLCD                    (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET)
@@ -225,7 +225,20 @@
 #define VERSATILE_SSMC_BASE            0x20000000	/* SSMC */
 #define VERSATILE_IB2_BASE             0x24000000	/* IB2 module */
 #define VERSATILE_MBX_BASE             0x40000000	/* MBX */
+
+/* PCI space */
 #define VERSATILE_PCI_BASE             0x41000000	/* PCI Interface */
+#define VERSATILE_PCI_CFG_BASE	       0x42000000
+#define VERSATILE_PCI_MEM_BASE0        0x44000000
+#define VERSATILE_PCI_MEM_BASE1        0x50000000
+#define VERSATILE_PCI_MEM_BASE2        0x60000000
+/* Sizes of above maps */
+#define VERSATILE_PCI_BASE_SIZE	       0x01000000
+#define VERSATILE_PCI_CFG_BASE_SIZE    0x02000000
+#define VERSATILE_PCI_MEM_BASE0_SIZE   0x0c000000	/* 32Mb */
+#define VERSATILE_PCI_MEM_BASE1_SIZE   0x10000000	/* 256Mb */
+#define VERSATILE_PCI_MEM_BASE2_SIZE   0x10000000	/* 256Mb */
+
 #define VERSATILE_SDRAM67_BASE         0x70000000	/* SDRAM banks 6 and 7 */
 #define VERSATILE_LT_BASE              0x80000000	/* Logic Tile expansion */
 
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 09ffeed..035cdcf 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -16,6 +16,9 @@
 
 #include <asm/mman.h>
 #include <asm/glue.h>
+#include <asm/shmparam.h>
+
+#define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
  *	Cache Model
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 658ffa3..08a4630 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -273,6 +273,33 @@
 #endif
 
 /*
+ * io{read,write}{8,16,32} macros
+ */
+#define ioread8(p)	({ unsigned int __v = __raw_readb(p); __v; })
+#define ioread16(p)	({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })
+#define ioread32(p)	({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })
+
+#define iowrite8(v,p)	__raw_writeb(v, p)
+#define iowrite16(v,p)	__raw_writew(cpu_to_le16(v), p)
+#define iowrite32(v,p)	__raw_writel(cpu_to_le32(v), p)
+
+#define ioread8_rep(p,d,c)	__raw_readsb(p,d,c)
+#define ioread16_rep(p,d,c)	__raw_readsw(p,d,c)
+#define ioread32_rep(p,d,c)	__raw_readsl(p,d,c)
+
+#define iowrite8_rep(p,s,c)	__raw_writesb(p,s,c)
+#define iowrite16_rep(p,s,c)	__raw_writesw(p,s,c)
+#define iowrite32_rep(p,s,c)	__raw_writesl(p,s,c)
+
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *addr);
+
+struct pci_dev;
+
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
+
+/*
  * can the hardware map this into one segment or not, given no other
  * constraints.
  */
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 31d3fc2..09a1451 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -20,7 +20,7 @@
 #define SIOCATALKDIFADDR       (SIOCPROTOPRIVATE + 0)
 
 struct atalk_addr {
-	__u16	s_net;
+	__be16	s_net;
 	__u8	s_node;
 };
 
@@ -33,8 +33,8 @@
 
 struct atalk_netrange {
 	__u8	nr_phase;
-	__u16	nr_firstnet;
-	__u16	nr_lastnet;
+	__be16	nr_firstnet;
+	__be16	nr_lastnet;
 };
 
 #ifdef __KERNEL__
@@ -70,8 +70,8 @@
 struct atalk_sock {
 	/* struct sock has to be the first member of atalk_sock */
 	struct sock	sk;
-	unsigned short	dest_net;
-	unsigned short	src_net;
+	__be16		dest_net;
+	__be16		src_net;
 	unsigned char	dest_node;
 	unsigned char	src_node;
 	unsigned char	dest_port;
@@ -95,9 +95,9 @@
 		deh_hops:4,
 		deh_len:10;
 #endif
-	__u16	deh_sum;
-	__u16	deh_dnet;
-	__u16	deh_snet;
+	__be16	deh_sum;
+	__be16	deh_dnet;
+	__be16	deh_snet;
 	__u8	deh_dnode;
 	__u8	deh_snode;
 	__u8	deh_dport;
@@ -142,24 +142,24 @@
 
 /* AppleTalk AARP headers */
 struct elapaarp {
-	__u16	hw_type;
+	__be16	hw_type;
 #define AARP_HW_TYPE_ETHERNET		1
 #define AARP_HW_TYPE_TOKENRING		2
-	__u16	pa_type;
+	__be16	pa_type;
 	__u8	hw_len;
 	__u8	pa_len;
 #define AARP_PA_ALEN			4
-	__u16	function;
+	__be16	function;
 #define AARP_REQUEST			1
 #define AARP_REPLY			2
 #define AARP_PROBE			3
 	__u8	hw_src[ETH_ALEN]	__attribute__ ((packed));
 	__u8	pa_src_zero		__attribute__ ((packed));
-	__u16	pa_src_net		__attribute__ ((packed));
+	__be16	pa_src_net		__attribute__ ((packed));
 	__u8	pa_src_node		__attribute__ ((packed));
 	__u8	hw_dst[ETH_ALEN]	__attribute__ ((packed));
 	__u8	pa_dst_zero		__attribute__ ((packed));
-	__u16	pa_dst_net		__attribute__ ((packed));
+	__be16	pa_dst_net		__attribute__ ((packed));
 	__u8	pa_dst_node		__attribute__ ((packed));	
 };
 
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index e38407a..561d4dc 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -14,6 +14,7 @@
 #define NETLINK_SELINUX		7	/* SELinux event notifications */
 #define NETLINK_ARPD		8
 #define NETLINK_AUDIT		9	/* auditing */
+#define NETLINK_FIB_LOOKUP	10	
 #define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
 #define NETLINK_IP6_FW		13
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index e6b5192..7240667 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -245,6 +245,7 @@
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
+#define SADB_SAFLAGS_NOPMTUDISC	0x20000000
 #define SADB_SAFLAGS_DECAP_DSCP	0x40000000
 #define SADB_SAFLAGS_NOECN	0x80000000
 
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index d68391a..f0d4233 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -196,6 +196,7 @@
 	__u8				flags;
 #define XFRM_STATE_NOECN	1
 #define XFRM_STATE_DECAP_DSCP	2
+#define XFRM_STATE_NOPMTUDISC	4
 };
 
 struct xfrm_usersa_id {
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 9e6368a..828a3a93 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -220,7 +220,7 @@
 	}
 }
 
-static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	skb->dev      = dev;
 	skb->pkt_type = PACKET_HOST;
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e5a5f6b..a4208a3 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -109,6 +109,20 @@
 #endif
 };
 
+struct fib_result_nl {
+	u32		fl_addr;   /* To be looked up*/ 
+	u32		fl_fwmark; 
+	unsigned char	fl_tos;
+	unsigned char   fl_scope;
+	unsigned char   tb_id_in;
+
+	unsigned char   tb_id;      /* Results */
+	unsigned char	prefixlen;
+	unsigned char	nh_sel;
+	unsigned char	type;
+	unsigned char	scope;
+	int             err;      
+};
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index ebc5282..dc107ff 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -65,9 +65,11 @@
 	SCTP_CMD_TIMER_START,	/* Start a timer.  */
 	SCTP_CMD_TIMER_RESTART,	/* Restart a timer. */
 	SCTP_CMD_TIMER_STOP,	/* Stop a timer. */
-	SCTP_CMD_COUNTER_RESET, /* Reset a counter. */
-	SCTP_CMD_COUNTER_INC,   /* Increment a counter. */
+	SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */
+	SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */
+	SCTP_CMD_INIT_COUNTER_INC,   /* Increment init counter. */
 	SCTP_CMD_INIT_RESTART,  /* High level, do init timer work. */
+	SCTP_CMD_COOKIEECHO_RESTART,  /* High level, do cookie-echo timer work. */
 	SCTP_CMD_INIT_FAILED,   /* High level, do init failure work. */
 	SCTP_CMD_REPORT_DUP,	/* Report a duplicate TSN.  */
 	SCTP_CMD_STRIKE,	/* Mark a strike against a transport.  */
@@ -118,7 +120,6 @@
 	int error;
 	sctp_state_t state;
 	sctp_event_timeout_t to;
-	sctp_counter_t counter;
 	void *ptr;
 	struct sctp_chunk *chunk;
 	struct sctp_association *asoc;
@@ -165,7 +166,6 @@
 SCTP_ARG_CONSTRUCTOR(U8,	__u8, u8)
 SCTP_ARG_CONSTRUCTOR(ERROR,     int, error)
 SCTP_ARG_CONSTRUCTOR(STATE,	sctp_state_t, state)
-SCTP_ARG_CONSTRUCTOR(COUNTER,	sctp_counter_t, counter)
 SCTP_ARG_CONSTRUCTOR(TO,	sctp_event_timeout_t, to)
 SCTP_ARG_CONSTRUCTOR(PTR,	void *, ptr)
 SCTP_ARG_CONSTRUCTOR(CHUNK,	struct sctp_chunk *, chunk)
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 2b76c0f..4868c7f 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -263,13 +263,6 @@
 enum { SCTP_MAX_DUP_TSNS = 16 };
 enum { SCTP_MAX_GABS = 16 };
 
-typedef enum {
-	SCTP_COUNTER_INIT_ERROR,
-} sctp_counter_t;
-
-/* How many counters does an association need? */
-#define SCTP_NUMBER_COUNTERS	5
-
 /* Here we define the default timers.  */
 
 /* cookie timer def = ? seconds */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 960abfa..ef27381 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -223,6 +223,22 @@
 extern int sctp_debug_flag;
 #define SCTP_DEBUG_PRINTK(whatever...) \
 	((void) (sctp_debug_flag && printk(KERN_DEBUG whatever)))
+#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \
+	if (sctp_debug_flag) { \
+		if (saddr->sa.sa_family == AF_INET6) { \
+			printk(KERN_DEBUG \
+			       lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \
+			       leadparm, \
+			       NIP6(saddr->v6.sin6_addr), \
+			       otherparms); \
+		} else { \
+			printk(KERN_DEBUG \
+			       lead "%u.%u.%u.%u" trail, \
+			       leadparm, \
+			       NIPQUAD(saddr->v4.sin_addr.s_addr), \
+			       otherparms); \
+		} \
+	}
 #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
 #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
 
@@ -236,6 +252,7 @@
 #else	/* SCTP_DEBUG */
 
 #define SCTP_DEBUG_PRINTK(whatever...)
+#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
 #define SCTP_ENABLE_DEBUG
 #define SCTP_DISABLE_DEBUG
 #define SCTP_ASSERT(expr, str, func)
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index f4fcee1..a53e08a 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -116,7 +116,8 @@
 sctp_state_fn_t sctp_sf_eat_sack_6_2;
 sctp_state_fn_t sctp_sf_tabort_8_4_8;
 sctp_state_fn_t sctp_sf_operr_notify;
-sctp_state_fn_t sctp_sf_t1_timer_expire;
+sctp_state_fn_t sctp_sf_t1_init_timer_expire;
+sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
 sctp_state_fn_t sctp_sf_t2_timer_expire;
 sctp_state_fn_t sctp_sf_t4_timer_expire;
 sctp_state_fn_t sctp_sf_t5_timer_expire;
@@ -258,7 +259,10 @@
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error);
+sctp_disposition_t  sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+					   __u16 error,
+					   const struct sctp_association *asoc,
+					   struct sctp_transport *transport);
 
 /* Prototypes for statetable processing. */
 
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6c24d9c..dfad4d3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -867,10 +867,13 @@
 	 */
 	unsigned long last_time_ecne_reduced;
 
-	/* active      : The current active state of this destination,
-	 *	       :  i.e. DOWN, UP, etc.
+	/* The number of times INIT has been sent on this transport. */
+	int init_sent_count;
+
+	/* state       : The current state of this destination,
+	 *             : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN.
 	 */
-	int active;
+	int state;
 
 	/* hb_allowed  : The current heartbeat state of this destination,
 	 *	       :  i.e. ALLOW-HB, NO-HEARTBEAT, etc.
@@ -1222,9 +1225,6 @@
 
 	/* sendbuf acct. policy.	*/
 	__u32 sndbuf_policy;
-
-	/* Name for debugging output... */
-	char *debug_name;
 };
 
 /* Recover the outter endpoint structure. */
@@ -1314,11 +1314,23 @@
 		 *	       : association. Normally this information is
 		 *	       : hashed or keyed for quick lookup and access
 		 *	       : of the TCB.
+		 *	       : The list is also initialized with the list
+		 *	       : of addresses passed with the sctp_connectx()
+		 *	       : call.
 		 *
 		 * It is a list of SCTP_transport's.
 		 */
 		struct list_head transport_addr_list;
 
+		/* transport_count
+		 *
+		 * Peer        : A count of the number of peer addresses
+		 * Transport   : in the Peer Transport Address List.
+		 * Address     :
+		 * Count       :
+		 */
+		__u16 transport_count;
+
 		/* port
 		 *   The transport layer port number.
 		 */
@@ -1486,6 +1498,9 @@
 	/* Transport to which SHUTDOWN chunk was last sent.  */
 	struct sctp_transport *shutdown_last_sent_to;
 
+	/* Transport to which INIT chunk was last sent.  */
+	struct sctp_transport *init_last_sent_to;
+
 	/* Next TSN    : The next TSN number to be assigned to a new
 	 *	       : DATA chunk.  This is sent in the INIT or INIT
 	 *	       : ACK chunk to the peer and incremented each
@@ -1549,8 +1564,11 @@
 	/* The message size at which SCTP fragmentation will occur. */
 	__u32 frag_point;
 
-	/* Currently only one counter is used to count INIT errors. */
-	int counters[SCTP_NUMBER_COUNTERS];
+	/* Counter used to count INIT errors. */
+	int init_err_counter;
+
+	/* Count the number of INIT cycles (for doubling timeout). */
+	int init_cycle;
 
 	/* Default send parameters. */
 	__u16 default_stream;
@@ -1708,6 +1726,8 @@
 void sctp_association_put(struct sctp_association *);
 void sctp_association_hold(struct sctp_association *);
 
+struct sctp_transport *sctp_assoc_choose_init_transport(
+	struct sctp_association *);
 struct sctp_transport *sctp_assoc_choose_shutdown_transport(
 	struct sctp_association *);
 void sctp_assoc_update_retran_path(struct sctp_association *);
@@ -1717,9 +1737,12 @@
 			    const union sctp_addr *laddr);
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
 				     const union sctp_addr *address,
-				     const int gfp);
+				     const int gfp,
+				     const int peer_state);
 void sctp_assoc_del_peer(struct sctp_association *asoc,
 			 const union sctp_addr *addr);
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+			 struct sctp_transport *peer);
 void sctp_assoc_control_transport(struct sctp_association *,
 				  struct sctp_transport *,
 				  sctp_transport_cmd_t, sctp_sn_error_t);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 2758e8c..f6328ae 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -111,6 +111,8 @@
 #define SCTP_GET_LOCAL_ADDRS_NUM	SCTP_GET_LOCAL_ADDRS_NUM
 	SCTP_GET_LOCAL_ADDRS, 	/* Get all local addresss. */
 #define SCTP_GET_LOCAL_ADDRS	SCTP_GET_LOCAL_ADDRS
+	SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
+#define SCTP_SOCKOPT_CONNECTX	SCTP_SOCKOPT_CONNECTX
 };
 
 /*
@@ -527,6 +529,7 @@
 enum sctp_spinfo_state {
 	SCTP_INACTIVE,
 	SCTP_ACTIVE,
+	SCTP_UNKNOWN = 0xffff  /* Value used for transport state unknown */
 };
 
 /*
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0e65e02..029522a 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -204,6 +204,7 @@
 	rwlock_t		lock;
 	struct list_head	*state_bydst;
 	struct list_head	*state_byspi;
+	int			(*init_flags)(struct xfrm_state *x);
 	void			(*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
 						struct xfrm_tmpl *tmpl,
 						xfrm_address_t *daddr, xfrm_address_t *saddr);
@@ -225,7 +226,7 @@
 	struct module		*owner;
 	__u8			proto;
 
-	int			(*init_state)(struct xfrm_state *x, void *args);
+	int			(*init_state)(struct xfrm_state *x);
 	void			(*destructor)(struct xfrm_state *);
 	int			(*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
 	int			(*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
@@ -839,6 +840,7 @@
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int xfrm_init_state(struct xfrm_state *x);
 extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 54640c0..10d0404 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -565,7 +565,7 @@
 			 *	numbers	we just happen to need. Now put the
 			 *	length in the lower two.
 			 */
-			*((__u16 *)skb->data) = htons(skb->len);
+			*((__be16 *)skb->data) = htons(skb->len);
 			ft = 1;
 		}
 		/*
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 876dbac7..192b529 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -401,7 +401,7 @@
 }
 
 /* Find a match for a specific network:node pair */
-static struct atalk_iface *atalk_find_interface(int net, int node)
+static struct atalk_iface *atalk_find_interface(__be16 net, int node)
 {
 	struct atalk_iface *iface;
 
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 0e98f22..514c85b 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -200,7 +200,7 @@
 	xfrm_state_put(x);
 }
 
-static int ah_init_state(struct xfrm_state *x, void *args)
+static int ah_init_state(struct xfrm_state *x)
 {
 	struct ah_data *ahp = NULL;
 	struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index eae84cc..ba57446 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -362,7 +362,7 @@
 	kfree(esp);
 }
 
-static int esp_init_state(struct xfrm_state *x, void *args)
+static int esp_init_state(struct xfrm_state *x)
 {
 	struct esp_data *esp = NULL;
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 563e7d6..cd8e45a 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -516,6 +516,60 @@
 #undef BRD1_OK
 }
 
+static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
+{
+	
+	struct fib_result       res;
+	struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, 
+							    .fwmark = frn->fl_fwmark,
+							    .tos = frn->fl_tos,
+							    .scope = frn->fl_scope } } };
+	if (tb) {
+		local_bh_disable();
+
+		frn->tb_id = tb->tb_id;
+		frn->err = tb->tb_lookup(tb, &fl, &res);
+
+		if (!frn->err) {
+			frn->prefixlen = res.prefixlen;
+			frn->nh_sel = res.nh_sel;
+			frn->type = res.type;
+			frn->scope = res.scope;
+		}
+		local_bh_enable();
+	}
+}
+
+static void nl_fib_input(struct sock *sk, int len)
+{
+	struct sk_buff *skb = NULL;
+        struct nlmsghdr *nlh = NULL;
+	struct fib_result_nl *frn;
+	int err;
+	u32 pid;     
+	struct fib_table *tb;
+	
+	skb = skb_recv_datagram(sk, 0, 0, &err);
+	nlh = (struct nlmsghdr *)skb->data;
+	
+	frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
+	tb = fib_get_table(frn->tb_id_in);
+
+	nl_fib_lookup(frn, tb);
+	
+	pid = nlh->nlmsg_pid;           /*pid of sending process */
+	NETLINK_CB(skb).groups = 0;     /* not in mcast group */
+	NETLINK_CB(skb).pid = 0;         /* from kernel */
+	NETLINK_CB(skb).dst_pid = pid;
+	NETLINK_CB(skb).dst_groups = 0;  /* unicast */
+	netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
+}    
+
+static void nl_fib_lookup_init(void)
+{
+      netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
+}
+
 static void fib_disable_ip(struct net_device *dev, int force)
 {
 	if (fib_sync_down(0, dev, force))
@@ -604,6 +658,7 @@
 
 	register_netdevice_notifier(&fib_netdev_notifier);
 	register_inetaddr_notifier(&fib_inetaddr_notifier);
+	nl_fib_lookup_init();
 }
 
 EXPORT_SYMBOL(inet_addr_type);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 1a23c52..2065944 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -236,15 +236,10 @@
 	t->props.mode = 1;
 	t->props.saddr.a4 = x->props.saddr.a4;
 	t->props.flags = x->props.flags;
-	
-	t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family);
-	if (t->type == NULL)
-		goto error;
-		
-	if (t->type->init_state(t, NULL))
+
+	if (xfrm_init_state(t))
 		goto error;
 
-	t->km.state = XFRM_STATE_VALID;
 	atomic_set(&t->tunnel_users, 1);
 out:
 	return t;
@@ -422,7 +417,7 @@
 	kfree(ipcd);
 }
 
-static int ipcomp_init_state(struct xfrm_state *x, void *args)
+static int ipcomp_init_state(struct xfrm_state *x)
 {
 	int err;
 	struct ipcomp_data *ipcd;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index af2392a..66620a9 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -33,6 +33,7 @@
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct iphdr *iph, *top_iph;
+	int flags;
 
 	iph = skb->nh.iph;
 	skb->h.ipiph = iph;
@@ -51,10 +52,13 @@
 
 	/* DS disclosed */
 	top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-	if (x->props.flags & XFRM_STATE_NOECN)
+
+	flags = x->props.flags;
+	if (flags & XFRM_STATE_NOECN)
 		IP_ECN_clear(top_iph);
 
-	top_iph->frag_off = iph->frag_off & htons(IP_DF);
+	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+		0 : (iph->frag_off & htons(IP_DF));
 	if (!top_iph->frag_off)
 		__ip_select_ident(top_iph, dst, 0);
 
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 223a2e8..050611d 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -7,12 +7,20 @@
  *
  */
 
+#include <net/ip.h>
 #include <net/xfrm.h>
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
 
 static struct xfrm_state_afinfo xfrm4_state_afinfo;
 
+static int xfrm4_init_flags(struct xfrm_state *x)
+{
+	if (ipv4_config.no_pmtu_disc)
+		x->props.flags |= XFRM_STATE_NOPMTUDISC;
+	return 0;
+}
+
 static void
 __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
 		     struct xfrm_tmpl *tmpl,
@@ -109,6 +117,7 @@
 static struct xfrm_state_afinfo xfrm4_state_afinfo = {
 	.family			= AF_INET,
 	.lock			= RW_LOCK_UNLOCKED,
+	.init_flags		= xfrm4_init_flags,
 	.init_tempsel		= __xfrm4_init_tempsel,
 	.state_lookup		= __xfrm4_state_lookup,
 	.find_acq		= __xfrm4_find_acq,
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 413191f..e1fe360e 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -84,7 +84,7 @@
 		handler->err_handler(skb, &arg);
 }
 
-static int ipip_init_state(struct xfrm_state *x, void *args)
+static int ipip_init_state(struct xfrm_state *x)
 {
 	if (!x->props.mode)
 		return -EINVAL;
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index e3ecf62..986fdfd 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -339,7 +339,7 @@
 	xfrm_state_put(x);
 }
 
-static int ah6_init_state(struct xfrm_state *x, void *args)
+static int ah6_init_state(struct xfrm_state *x)
 {
 	struct ah_data *ahp = NULL;
 	struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index be7095d..324db62 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -296,7 +296,7 @@
 	kfree(esp);
 }
 
-static int esp6_init_state(struct xfrm_state *x, void *args)
+static int esp6_init_state(struct xfrm_state *x)
 {
 	struct esp_data *esp = NULL;
 
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 6cde531..423feb46 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -234,14 +234,9 @@
 	t->props.mode = 1;
 	memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
 
-	t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family);
-	if (t->type == NULL)
+	if (xfrm_init_state(t))
 		goto error;
 
-	if (t->type->init_state(t, NULL))
-		goto error;
-
-	t->km.state = XFRM_STATE_VALID;
 	atomic_set(&t->tunnel_users, 1);
 
 out:
@@ -420,7 +415,7 @@
 	xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
 }
 
-static int ipcomp6_init_state(struct xfrm_state *x, void *args)
+static int ipcomp6_init_state(struct xfrm_state *x)
 {
 	int err;
 	struct ipcomp_data *ipcd;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index ffcadd6..60c26c8 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -466,7 +466,7 @@
 	return;
 }
 
-static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+static int xfrm6_tunnel_init_state(struct xfrm_state *x)
 {
 	if (!x->props.mode)
 		return -EINVAL;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 98b72f2..4879743 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -690,6 +690,8 @@
 		sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
 	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
 		sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
+	if (x->props.flags & XFRM_STATE_NOPMTUDISC)
+		sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC;
 
 	/* hard time */
 	if (hsc & 2) {
@@ -974,6 +976,8 @@
 		x->props.flags |= XFRM_STATE_NOECN;
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
 		x->props.flags |= XFRM_STATE_DECAP_DSCP;
+	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
+		x->props.flags |= XFRM_STATE_NOPMTUDISC;
 
 	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
 	if (lifetime != NULL) {
@@ -1096,17 +1100,11 @@
 		}
 	}
 
-	x->type = xfrm_get_type(proto, x->props.family);
-	if (x->type == NULL) {
-		err = -ENOPROTOOPT;
+	err = xfrm_init_state(x);
+	if (err)
 		goto out;
-	}
-	if (x->type->init_state(x, NULL)) {
-		err = -EINVAL;
-		goto out;
-	}
+
 	x->km.seq = hdr->sadb_msg_seq;
-	x->km.state = XFRM_STATE_VALID;
 	return x;
 
 out:
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 663843d..7ae6aa7 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -191,10 +191,6 @@
 	asoc->last_cwr_tsn = asoc->ctsn_ack_point;
 	asoc->unack_data = 0;
 
-	SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n",
-			  asoc->ep->debug_name,
-			  asoc->ctsn_ack_point);
-
 	/* ADDIP Section 4.1 Asconf Chunk Procedures
 	 *
 	 * When an endpoint has an ASCONF signaled change to be sent to the
@@ -211,6 +207,7 @@
 
 	/* Make an empty list of remote transport addresses.  */
 	INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
+	asoc->peer.transport_count = 0;
 
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
@@ -288,6 +285,7 @@
 
 	asoc->base.malloced = 1;
 	SCTP_DBG_OBJCNT_INC(assoc);
+	SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc);
 
 	return asoc;
 
@@ -356,6 +354,8 @@
 		sctp_transport_free(transport);
 	}
 
+	asoc->peer.transport_count = 0;
+
 	/* Free any cached ASCONF_ACK chunk. */
 	if (asoc->addip_last_asconf_ack)
 		sctp_chunk_free(asoc->addip_last_asconf_ack);
@@ -400,7 +400,7 @@
 	/* If the primary path is changing, assume that the
 	 * user wants to use this new path.
 	 */
-	if (transport->active)
+	if (transport->state != SCTP_INACTIVE)
 		asoc->peer.active_path = transport;
 
 	/*
@@ -428,10 +428,58 @@
 	transport->cacc.next_tsn_at_change = asoc->next_tsn;
 }
 
+/* Remove a transport from an association.  */
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+			struct sctp_transport *peer)
+{
+	struct list_head	*pos;
+	struct sctp_transport	*transport;
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ",
+				 " port: %d\n",
+				 asoc,
+				 (&peer->ipaddr),
+				 peer->ipaddr.v4.sin_port);
+
+	/* If we are to remove the current retran_path, update it
+	 * to the next peer before removing this peer from the list.
+	 */
+	if (asoc->peer.retran_path == peer)
+		sctp_assoc_update_retran_path(asoc);
+
+	/* Remove this peer from the list. */
+	list_del(&peer->transports);
+
+	/* Get the first transport of asoc. */
+	pos = asoc->peer.transport_addr_list.next;
+	transport = list_entry(pos, struct sctp_transport, transports);
+
+	/* Update any entries that match the peer to be deleted. */
+	if (asoc->peer.primary_path == peer)
+		sctp_assoc_set_primary(asoc, transport);
+	if (asoc->peer.active_path == peer)
+		asoc->peer.active_path = transport;
+	if (asoc->peer.last_data_from == peer)
+		asoc->peer.last_data_from = transport;
+
+	/* If we remove the transport an INIT was last sent to, set it to
+	 * NULL. Combined with the update of the retran path above, this
+	 * will cause the next INIT to be sent to the next available
+	 * transport, maintaining the cycle.
+	 */
+	if (asoc->init_last_sent_to == peer)
+		asoc->init_last_sent_to = NULL;
+
+	asoc->peer.transport_count--;
+
+	sctp_transport_free(peer);
+}
+
 /* Add a transport address to an association.  */
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 					   const union sctp_addr *addr,
-					   int gfp)
+					   const int gfp,
+					   const int peer_state)
 {
 	struct sctp_transport *peer;
 	struct sctp_sock *sp;
@@ -442,14 +490,25 @@
 	/* AF_INET and AF_INET6 share common port field. */
 	port = addr->v4.sin_port;
 
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
+				 " port: %d state:%s\n",
+				 asoc,
+				 addr,
+				 addr->v4.sin_port,
+				 peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
+
 	/* Set the port if it has not been set yet.  */
 	if (0 == asoc->peer.port)
 		asoc->peer.port = port;
 
 	/* Check to see if this is a duplicate. */
 	peer = sctp_assoc_lookup_paddr(asoc, addr);
-	if (peer)
+	if (peer) {
+		if (peer_state == SCTP_ACTIVE &&
+		    peer->state == SCTP_UNKNOWN)
+		     peer->state = SCTP_ACTIVE;
 		return peer;
+	}
 
 	peer = sctp_transport_new(addr, gfp);
 	if (!peer)
@@ -516,8 +575,12 @@
 	/* Set the transport's RTO.initial value */
 	peer->rto = asoc->rto_initial;
 
+	/* Set the peer's active state. */
+	peer->state = peer_state;
+
 	/* Attach the remote transport to our asoc.  */
 	list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+	asoc->peer.transport_count++;
 
 	/* If we do not yet have a primary path, set one.  */
 	if (!asoc->peer.primary_path) {
@@ -525,8 +588,9 @@
 		asoc->peer.retran_path = peer;
 	}
 
-	if (asoc->peer.active_path == asoc->peer.retran_path)
+	if (asoc->peer.active_path == asoc->peer.retran_path) {
 		asoc->peer.retran_path = peer;
+	}
 
 	return peer;
 }
@@ -537,37 +601,16 @@
 {
 	struct list_head	*pos;
 	struct list_head	*temp;
-	struct sctp_transport	*peer = NULL;
 	struct sctp_transport	*transport;
 
 	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
 		transport = list_entry(pos, struct sctp_transport, transports);
 		if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) {
-			peer = transport;
-			list_del(pos);
+			/* Do book keeping for removing the peer and free it. */
+			sctp_assoc_rm_peer(asoc, transport);
 			break;
 		}
 	}
-
-	/* The address we want delete is not in the association. */
-	if (!peer)
-		return;
-
-	/* Get the first transport of asoc. */ 
-	pos = asoc->peer.transport_addr_list.next;
-	transport = list_entry(pos, struct sctp_transport, transports);
-
-	/* Update any entries that match the peer to be deleted. */  
-	if (asoc->peer.primary_path == peer)
-		sctp_assoc_set_primary(asoc, transport);
-	if (asoc->peer.active_path == peer)
-		asoc->peer.active_path = transport;
-	if (asoc->peer.retran_path == peer)
-		asoc->peer.retran_path = transport;
-	if (asoc->peer.last_data_from == peer)
-		asoc->peer.last_data_from = transport;
-
-	sctp_transport_free(peer);
 }
 
 /* Lookup a transport by address. */
@@ -608,12 +651,12 @@
 	/* Record the transition on the transport.  */
 	switch (command) {
 	case SCTP_TRANSPORT_UP:
-		transport->active = SCTP_ACTIVE;
+		transport->state = SCTP_ACTIVE;
 		spc_state = SCTP_ADDR_AVAILABLE;
 		break;
 
 	case SCTP_TRANSPORT_DOWN:
-		transport->active = SCTP_INACTIVE;
+		transport->state = SCTP_INACTIVE;
 		spc_state = SCTP_ADDR_UNREACHABLE;
 		break;
 
@@ -643,7 +686,7 @@
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
 		t = list_entry(pos, struct sctp_transport, transports);
 
-		if (!t->active)
+		if (t->state == SCTP_INACTIVE)
 			continue;
 		if (!first || t->last_time_heard > first->last_time_heard) {
 			second = first;
@@ -663,7 +706,7 @@
 	 * [If the primary is active but not most recent, bump the most
 	 * recently used transport.]
 	 */
-	if (asoc->peer.primary_path->active &&
+	if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
 	    first != asoc->peer.primary_path) {
 		second = first;
 		first = asoc->peer.primary_path;
@@ -958,7 +1001,7 @@
 					   transports);
 			if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
 				sctp_assoc_add_peer(asoc, &trans->ipaddr,
-						    GFP_ATOMIC);
+						    GFP_ATOMIC, SCTP_ACTIVE);
 		}
 
 		asoc->ctsn_ack_point = asoc->next_tsn - 1;
@@ -998,7 +1041,7 @@
 
 		/* Try to find an active transport. */
 
-		if (t->active) {
+		if (t->state != SCTP_INACTIVE) {
 			break;
 		} else {
 			/* Keep track of the next transport in case
@@ -1019,6 +1062,40 @@
 	}
 
 	asoc->peer.retran_path = t;
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+				 " %p addr: ",
+				 " port: %d\n",
+				 asoc,
+				 (&t->ipaddr),
+				 t->ipaddr.v4.sin_port);
+}
+
+/* Choose the transport for sending a INIT packet.  */
+struct sctp_transport *sctp_assoc_choose_init_transport(
+	struct sctp_association *asoc)
+{
+	struct sctp_transport *t;
+
+	/* Use the retran path. If the last INIT was sent over the
+	 * retran path, update the retran path and use it.
+	 */
+	if (!asoc->init_last_sent_to) {
+		t = asoc->peer.active_path;
+	} else {
+		if (asoc->init_last_sent_to == asoc->peer.retran_path)
+			sctp_assoc_update_retran_path(asoc);
+		t = asoc->peer.retran_path;
+	}
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+				 " %p addr: ",
+				 " port: %d\n",
+				 asoc,
+				 (&t->ipaddr),
+				 t->ipaddr.v4.sin_port);
+
+	return t;
 }
 
 /* Choose the transport for sending a SHUTDOWN packet.  */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 334f617..2ec0320 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -134,7 +134,6 @@
 	ep->last_key = ep->current_key = 0;
 	ep->key_changed_at = jiffies;
 
-	ep->debug_name = "unnamedEndpoint";
 	return ep;
 }
 
diff --git a/net/sctp/input.c b/net/sctp/input.c
index fffc880..339f7ac 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -353,7 +353,7 @@
 
 	sctp_do_sm(SCTP_EVENT_T_OTHER,
 		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
-		   asoc->state, asoc->ep, asoc, NULL,
+		   asoc->state, asoc->ep, asoc, t,
 		   GFP_ATOMIC);
 
 }
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1b2d4adc..4eb81a1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -682,9 +682,9 @@
 
 		if (!new_transport) {
 			new_transport = asoc->peer.active_path;
-		} else if (!new_transport->active) {
-			/* If the chunk is Heartbeat or Heartbeat Ack, 
-			 * send it to chunk->transport, even if it's 
+		} else if (new_transport->state == SCTP_INACTIVE) {
+			/* If the chunk is Heartbeat or Heartbeat Ack,
+			 * send it to chunk->transport, even if it's
 			 * inactive.
 			 *
 			 * 3.3.6 Heartbeat Acknowledgement:
@@ -840,7 +840,8 @@
 			 * Otherwise, we want to use the active path.
 			 */
 			new_transport = chunk->transport;
-			if (!new_transport || !new_transport->active)
+			if (!new_transport ||
+			    new_transport->state == SCTP_INACTIVE)
 				new_transport = asoc->peer.active_path;
 
 			/* Change packets if necessary.  */
@@ -1454,7 +1455,7 @@
 			/* Mark the destination transport address as
 			 * active if it is not so marked.
 			 */
-			if (!transport->active) {
+			if (transport->state == SCTP_INACTIVE) {
 				sctp_assoc_control_transport(
 					transport->asoc,
 					transport,
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 33ac8bf..5baed9b 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1830,7 +1830,7 @@
 	 * be a a better choice than any of the embedded addresses.
 	 */
 	if (peer_addr)
-		if(!sctp_assoc_add_peer(asoc, peer_addr, gfp))
+		if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
 			goto nomem;
 
 	/* Process the initialization parameters.  */
@@ -1841,6 +1841,14 @@
                         goto clean_up;
 	}
 
+	/* Walk list of transports, removing transports in the UNKNOWN state. */
+	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+		transport = list_entry(pos, struct sctp_transport, transports);
+		if (transport->state == SCTP_UNKNOWN) {
+			sctp_assoc_rm_peer(asoc, transport);
+		}
+	}
+
 	/* The fixed INIT headers are always in network byte
 	 * order.
 	 */
@@ -1906,7 +1914,8 @@
 	 * stream sequence number shall be set to 0.
 	 */
 
-	/* Allocate storage for the negotiated streams if it is not a temporary 	 * association.
+	/* Allocate storage for the negotiated streams if it is not a temporary
+ 	 * association.
 	 */
 	if (!asoc->temp) {
 		int assoc_id;
@@ -1952,6 +1961,9 @@
 		list_del_init(pos);
 		sctp_transport_free(transport);
 	}
+
+	asoc->peer.transport_count = 0;
+
 nomem:
 	return 0;
 }
@@ -1995,7 +2007,7 @@
 		af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
 		scope = sctp_scope(peer_addr);
 		if (sctp_in_scope(&addr, scope))
-			if (!sctp_assoc_add_peer(asoc, &addr, gfp))
+			if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
 				return 0;
 		break;
 
@@ -2396,7 +2408,7 @@
 	 	 * Due to Resource Shortage'.
 	 	 */
 
-		peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC);
+		peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
 		if (!peer)
 			return SCTP_ERROR_RSRC_LOW;
 
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index f65fa44..778639d 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -414,11 +414,13 @@
 	 */
 	asoc->overall_error_count++;
 
-	if (transport->active &&
+	if (transport->state != SCTP_INACTIVE &&
 	    (transport->error_count++ >= transport->max_retrans)) {
-		SCTP_DEBUG_PRINTK("transport_strike: transport "
-				  "IP:%d.%d.%d.%d failed.\n",
-				  NIPQUAD(transport->ipaddr.v4.sin_addr));
+		SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
+					 " transport IP: port:%d failed.\n",
+					 asoc,
+					 (&transport->ipaddr),
+					 transport->ipaddr.v4.sin_port);
 		sctp_assoc_control_transport(asoc, transport,
 					     SCTP_TRANSPORT_DOWN,
 					     SCTP_FAILED_THRESHOLD);
@@ -593,7 +595,7 @@
 	/* Mark the destination transport address as active if it is not so
 	 * marked.
 	 */
-	if (!t->active)
+	if (t->state == SCTP_INACTIVE)
 		sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
 					     SCTP_HEARTBEAT_SUCCESS);
 
@@ -665,8 +667,11 @@
 
 	asoc->state = state;
 
+	SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n",
+			  asoc, sctp_state_tbl[state]);
+
 	if (sctp_style(sk, TCP)) {
-		/* Change the sk->sk_state of a TCP-style socket that has 
+		/* Change the sk->sk_state of a TCP-style socket that has
 		 * sucessfully completed a connect() call.
 		 */
 		if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
@@ -678,6 +683,16 @@
 			sk->sk_shutdown |= RCV_SHUTDOWN;
 	}
 
+	if (sctp_state(asoc, COOKIE_WAIT)) {
+		/* Reset init timeouts since they may have been
+		 * increased due to timer expirations.
+		 */
+		asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+			asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT];
+		asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
+			asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE];
+	}
+
 	if (sctp_state(asoc, ESTABLISHED) ||
 	    sctp_state(asoc, CLOSED) ||
 	    sctp_state(asoc, SHUTDOWN_RECEIVED)) {
@@ -1120,10 +1135,10 @@
 			 * to be executed only during failed attempts of
 			 * association establishment.
 			 */
-			if ((asoc->peer.retran_path != 
-			     asoc->peer.primary_path) && 
-			    (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) {
-				sctp_add_cmd_sf(commands, 
+			if ((asoc->peer.retran_path !=
+			     asoc->peer.primary_path) &&
+			    (asoc->init_err_counter > 0)) {
+				sctp_add_cmd_sf(commands,
 				                SCTP_CMD_FORCE_PRIM_RETRAN,
 						SCTP_NULL());
 			}
@@ -1237,18 +1252,67 @@
 				sctp_association_put(asoc);
 			break;
 
+		case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
+			chunk = cmd->obj.ptr;
+			t = sctp_assoc_choose_init_transport(asoc);
+			asoc->init_last_sent_to = t;
+			chunk->transport = t;
+			t->init_sent_count++;
+			break;
+
 		case SCTP_CMD_INIT_RESTART:
 			/* Do the needed accounting and updates
 			 * associated with restarting an initialization
-			 * timer.
+			 * timer. Only multiply the timeout by two if
+			 * all transports have been tried at the current
+			 * timeout.
 			 */
-			asoc->counters[SCTP_COUNTER_INIT_ERROR]++;
-			asoc->timeouts[cmd->obj.to] *= 2;
-			if (asoc->timeouts[cmd->obj.to] >
+			t = asoc->init_last_sent_to;
+			asoc->init_err_counter++;
+
+			if (t->init_sent_count > (asoc->init_cycle + 1)) {
+				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2;
+				if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] >
+				    asoc->max_init_timeo) {
+					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+						asoc->max_init_timeo;
+				}
+				asoc->init_cycle++;
+				SCTP_DEBUG_PRINTK(
+					"T1 INIT Timeout adjustment"
+					" init_err_counter: %d"
+					" cycle: %d"
+					" timeout: %d\n",
+					asoc->init_err_counter,
+					asoc->init_cycle,
+					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
+			}
+
+			sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
+					SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+			break;
+
+		case SCTP_CMD_COOKIEECHO_RESTART:
+			/* Do the needed accounting and updates
+			 * associated with restarting an initialization
+			 * timer. Only multiply the timeout by two if
+			 * all transports have been tried at the current
+			 * timeout.
+			 */
+			asoc->init_err_counter++;
+
+			asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2;
+			if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] >
 			    asoc->max_init_timeo) {
-				asoc->timeouts[cmd->obj.to] =
+				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
 					asoc->max_init_timeo;
 			}
+			SCTP_DEBUG_PRINTK(
+				"T1 COOKIE Timeout adjustment"
+				" init_err_counter: %d"
+				" timeout: %d\n",
+				asoc->init_err_counter,
+				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 
 			/* If we've sent any data bundled with
 			 * COOKIE-ECHO we need to resend.
@@ -1261,7 +1325,7 @@
 
 			sctp_add_cmd_sf(commands,
 					SCTP_CMD_TIMER_RESTART,
-					SCTP_TO(cmd->obj.to));
+					SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
 			break;
 
 		case SCTP_CMD_INIT_FAILED:
@@ -1273,12 +1337,13 @@
 					      subtype, chunk, cmd->obj.u32);
 			break;
 
-		case SCTP_CMD_COUNTER_INC:
-			asoc->counters[cmd->obj.counter]++;
+		case SCTP_CMD_INIT_COUNTER_INC:
+			asoc->init_err_counter++;
 			break;
 
-		case SCTP_CMD_COUNTER_RESET:
-			asoc->counters[cmd->obj.counter] = 0;
+		case SCTP_CMD_INIT_COUNTER_RESET:
+			asoc->init_err_counter = 0;
+			asoc->init_cycle = 0;
 			break;
 
 		case SCTP_CMD_REPORT_DUP:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 8e01b8f..0581896 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -533,6 +533,9 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT,
 			SCTP_PEER_INIT(initchunk));
 
+	/* Reset init error count upon receipt of INIT-ACK.  */
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
+
 	/* 5.1 C) "A" shall stop the T1-init timer and leave
 	 * COOKIE-WAIT state.  "A" shall then ... start the T1-cookie
 	 * timer, and enter the COOKIE-ECHOED state.
@@ -775,8 +778,7 @@
 	 * from the COOKIE-ECHOED state to the COOKIE-WAIT
 	 * state is performed.
 	 */
-	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
-	                SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
 
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
@@ -1019,10 +1021,22 @@
 	link = sctp_assoc_lookup_paddr(asoc, &from_addr);
 
 	/* This should never happen, but lets log it if so.  */
-	if (!link) {
-		printk(KERN_WARNING
-		       "%s: Could not find address %d.%d.%d.%d\n",
-		       __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr));
+	if (unlikely(!link)) {
+		if (from_addr.sa.sa_family == AF_INET6) {
+			printk(KERN_WARNING
+			       "%s association %p could not find address "
+			       "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+			       __FUNCTION__,
+			       asoc,
+			       NIP6(from_addr.v6.sin6_addr));
+		} else {
+			printk(KERN_WARNING
+			       "%s association %p could not find address "
+			       "%u.%u.%u.%u\n",
+			       __FUNCTION__,
+			       asoc,
+			       NIPQUAD(from_addr.v4.sin_addr.s_addr));
+		}
 		return SCTP_DISPOSITION_DISCARD;
 	}
 
@@ -2095,9 +2109,7 @@
 	sctp_errhdr_t *err;
 	struct sctp_chunk *reply;
 	struct sctp_bind_addr *bp;
-	int attempts;
-
-	attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
+	int attempts = asoc->init_err_counter + 1;
 
 	if (attempts >= asoc->max_init_attempts) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -2157,8 +2169,7 @@
 	/* Cast away the const modifier, as we want to just
 	 * rerun it through as a sideffect.
 	 */
-	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
-			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL());
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
@@ -2281,8 +2292,7 @@
 	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
- 	sctp_stop_t1_and_abort(commands, error);
-	return SCTP_DISPOSITION_ABORT;
+	return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
 }
 
 /*
@@ -2294,8 +2304,8 @@
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR);
- 	return SCTP_DISPOSITION_ABORT;
+	return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+				      (struct sctp_transport *)arg);
 }
 
 /*
@@ -2318,8 +2328,12 @@
  *
  * This is common code called by several sctp_sf_*_abort() functions above.
  */
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
+sctp_disposition_t  sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+					   __u16 error,
+					   const struct sctp_association *asoc,
+					   struct sctp_transport *transport)
 {
+	SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
 			SCTP_STATE(SCTP_STATE_CLOSED));
 	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2328,6 +2342,7 @@
 	/* CMD_INIT_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 			SCTP_U32(error));
+	return SCTP_DISPOSITION_ABORT;
 }
 
 /*
@@ -3805,6 +3820,10 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC,
 			SCTP_ASOC((struct sctp_association *) asoc));
 
+	/* Choose transport for INIT. */
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+			SCTP_CHUNK(repl));
+
 	/* After sending the INIT, "A" starts the T1-init timer and
 	 * enters the COOKIE-WAIT state.
 	 */
@@ -4589,7 +4608,7 @@
 }
 
 /*
- * sctp_sf_t1_timer_expire
+ * sctp_sf_t1_init_timer_expire
  *
  * Section: 4 Note: 2
  * Verification Tag:
@@ -4603,7 +4622,59 @@
  *     endpoint MUST abort the initialization process and report the
  *     error to SCTP user.
  *
- *   3) If the T1-cookie timer expires, the endpoint MUST retransmit
+ * Outputs
+ * (timers, events)
+ *
+ */
+sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
+					   const struct sctp_association *asoc,
+					   const sctp_subtype_t type,
+					   void *arg,
+					   sctp_cmd_seq_t *commands)
+{
+	struct sctp_chunk *repl = NULL;
+	struct sctp_bind_addr *bp;
+	int attempts = asoc->init_err_counter + 1;
+
+	SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
+
+	if (attempts < asoc->max_init_attempts) {
+		bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
+		repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
+		if (!repl)
+			return SCTP_DISPOSITION_NOMEM;
+
+		/* Choose transport for INIT. */
+		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+				SCTP_CHUNK(repl));
+
+		/* Issue a sideeffect to do the needed accounting. */
+		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+	} else {
+		SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
+				  " max_init_attempts: %d\n",
+				  attempts, asoc->max_init_attempts);
+		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+				SCTP_U32(SCTP_ERROR_NO_ERROR));
+		return SCTP_DISPOSITION_DELETE_TCB;
+	}
+
+	return SCTP_DISPOSITION_CONSUME;
+}
+
+/*
+ * sctp_sf_t1_cookie_timer_expire
+ *
+ * Section: 4 Note: 2
+ * Verification Tag:
+ * Inputs
+ * (endpoint, asoc)
+ *
+ *  RFC 2960 Section 4 Notes
+ *  3) If the T1-cookie timer expires, the endpoint MUST retransmit
  *     COOKIE ECHO and re-start the T1-cookie timer without changing
  *     state.  This MUST be repeated up to 'Max.Init.Retransmits' times.
  *     After that, the endpoint MUST abort the initialization process and
@@ -4613,46 +4684,26 @@
  * (timers, events)
  *
  */
-sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep,
 					   const struct sctp_association *asoc,
 					   const sctp_subtype_t type,
 					   void *arg,
 					   sctp_cmd_seq_t *commands)
 {
-	struct sctp_chunk *repl;
-	struct sctp_bind_addr *bp;
-	sctp_event_timeout_t timer = (sctp_event_timeout_t) arg;
-	int timeout;
-	int attempts;
+	struct sctp_chunk *repl = NULL;
+	int attempts = asoc->init_err_counter + 1;
 
-	timeout = asoc->timeouts[timer];
-	attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
-	repl = NULL;
-
-	SCTP_DEBUG_PRINTK("Timer T1 expired.\n");
+	SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
 
 	if (attempts < asoc->max_init_attempts) {
-		switch (timer) {
-		case SCTP_EVENT_TIMEOUT_T1_INIT:
-			bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
-			repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
-			break;
-
-		case SCTP_EVENT_TIMEOUT_T1_COOKIE:
-			repl = sctp_make_cookie_echo(asoc, NULL);
-			break;
-
-		default:
-			BUG();
-			break;
-		};
-
+		repl = sctp_make_cookie_echo(asoc, NULL);
 		if (!repl)
-			goto nomem;
+			return SCTP_DISPOSITION_NOMEM;
 
 		/* Issue a sideeffect to do the needed accounting. */
-		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
-				SCTP_TO(timer));
+		sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
+
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 	} else {
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -4661,9 +4712,6 @@
 	}
 
 	return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-	return SCTP_DISPOSITION_NOMEM;
 }
 
 /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 8967846..75ef1040 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -783,7 +783,8 @@
 	/* SCTP_STATE_COOKIE_WAIT */ \
 	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
-	{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+	{.fn = sctp_sf_t1_cookie_timer_expire, \
+	 .name = "sctp_sf_t1_cookie_timer_expire"}, \
 	/* SCTP_STATE_ESTABLISHED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_SHUTDOWN_PENDING */ \
@@ -802,7 +803,8 @@
 	/* SCTP_STATE_CLOSED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_COOKIE_WAIT */ \
-	{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+	{.fn = sctp_sf_t1_init_timer_expire, \
+	 .name = "sctp_sf_t1_init_timer_expire"}, \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_ESTABLISHED */ \
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e6926cb..aad55dc 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -262,18 +262,18 @@
  *             sockaddr_in6 [RFC 2553]),
  *   addr_len - the size of the address structure.
  */
-SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
 {
 	int retval = 0;
 
 	sctp_lock_sock(sk);
 
-	SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n",
-			  sk, uaddr, addr_len);
+	SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n",
+			  sk, addr, addr_len);
 
 	/* Disallow binding twice. */
 	if (!sctp_sk(sk)->ep->base.bind_addr.port)
-		retval = sctp_do_bind(sk, (union sctp_addr *)uaddr,
+		retval = sctp_do_bind(sk, (union sctp_addr *)addr,
 				      addr_len);
 	else
 		retval = -EINVAL;
@@ -318,23 +318,27 @@
 	unsigned short snum;
 	int ret = 0;
 
-	SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n",
-			  sk, addr, len);
-
 	/* Common sockaddr verification. */
 	af = sctp_sockaddr_af(sp, addr, len);
-	if (!af)
+	if (!af) {
+		SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n",
+				  sk, addr, len);
 		return -EINVAL;
+	}
+
+	snum = ntohs(addr->v4.sin_port);
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ",
+				 ", port: %d, new port: %d, len: %d)\n",
+				 sk,
+				 addr,
+				 bp->port, snum,
+				 len);
 
 	/* PF specific bind() address verification. */
 	if (!sp->pf->bind_verify(sp, addr))
 		return -EADDRNOTAVAIL;
 
-	snum= ntohs(addr->v4.sin_port);
-
-	SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n",
-			  bp->port, snum);
-
 	/* We must either be unbound, or bind to the same port.  */
 	if (bp->port && (snum != bp->port)) {
 		SCTP_DEBUG_PRINTK("sctp_do_bind:"
@@ -816,7 +820,8 @@
  *
  * Basically do nothing but copying the addresses from user to kernel
  * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
- * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
+ * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
+ * from userspace.
  *
  * We don't use copy_from_user() for optimization: we first do the
  * sanity checks (buffer size -fast- and access check-healthy
@@ -913,6 +918,243 @@
 	return err;
 }
 
+/* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
+ *
+ * Common routine for handling connect() and sctp_connectx().
+ * Connect will come in with just a single address.
+ */
+static int __sctp_connect(struct sock* sk,
+			  struct sockaddr *kaddrs,
+			  int addrs_size)
+{
+	struct sctp_sock *sp;
+	struct sctp_endpoint *ep;
+	struct sctp_association *asoc = NULL;
+	struct sctp_association *asoc2;
+	struct sctp_transport *transport;
+	union sctp_addr to;
+	struct sctp_af *af;
+	sctp_scope_t scope;
+	long timeo;
+	int err = 0;
+	int addrcnt = 0;
+	int walk_size = 0;
+	struct sockaddr *sa_addr;
+	void *addr_buf;
+
+	sp = sctp_sk(sk);
+	ep = sp->ep;
+
+	/* connect() cannot be done on a socket that is already in ESTABLISHED
+	 * state - UDP-style peeled off socket or a TCP-style socket that
+	 * is already connected.
+	 * It cannot be done even on a TCP-style listening socket.
+	 */
+	if (sctp_sstate(sk, ESTABLISHED) ||
+	    (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
+		err = -EISCONN;
+		goto out_free;
+	}
+
+	/* Walk through the addrs buffer and count the number of addresses. */
+	addr_buf = kaddrs;
+	while (walk_size < addrs_size) {
+		sa_addr = (struct sockaddr *)addr_buf;
+		af = sctp_get_af_specific(sa_addr->sa_family);
+
+		/* If the address family is not supported or if this address
+		 * causes the address buffer to overflow return EINVAL.
+		 */
+		if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
+			err = -EINVAL;
+			goto out_free;
+		}
+
+		err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr,
+				       af->sockaddr_len);
+		if (err)
+			goto out_free;
+
+		memcpy(&to, sa_addr, af->sockaddr_len);
+		to.v4.sin_port = ntohs(to.v4.sin_port);
+
+		/* Check if there already is a matching association on the
+		 * endpoint (other than the one created here).
+		 */
+		asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
+		if (asoc2 && asoc2 != asoc) {
+			if (asoc2->state >= SCTP_STATE_ESTABLISHED)
+				err = -EISCONN;
+			else
+				err = -EALREADY;
+			goto out_free;
+		}
+
+		/* If we could not find a matching association on the endpoint,
+		 * make sure that there is no peeled-off association matching
+		 * the peer address even on another socket.
+		 */
+		if (sctp_endpoint_is_peeled_off(ep, &to)) {
+			err = -EADDRNOTAVAIL;
+			goto out_free;
+		}
+
+		if (!asoc) {
+			/* If a bind() or sctp_bindx() is not called prior to
+			 * an sctp_connectx() call, the system picks an
+			 * ephemeral port and will choose an address set
+			 * equivalent to binding with a wildcard address.
+			 */
+			if (!ep->base.bind_addr.port) {
+				if (sctp_autobind(sk)) {
+					err = -EAGAIN;
+					goto out_free;
+				}
+			}
+
+			scope = sctp_scope(&to);
+			asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
+			if (!asoc) {
+				err = -ENOMEM;
+				goto out_free;
+			}
+		}
+
+		/* Prime the peer's transport structures.  */
+		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
+						SCTP_UNKNOWN);
+		if (!transport) {
+			err = -ENOMEM;
+			goto out_free;
+		}
+
+		addrcnt++;
+		addr_buf += af->sockaddr_len;
+		walk_size += af->sockaddr_len;
+	}
+
+	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
+	if (err < 0) {
+		goto out_free;
+	}
+
+	err = sctp_primitive_ASSOCIATE(asoc, NULL);
+	if (err < 0) {
+		goto out_free;
+	}
+
+	/* Initialize sk's dport and daddr for getpeername() */
+	inet_sk(sk)->dport = htons(asoc->peer.port);
+	af = sctp_get_af_specific(to.sa.sa_family);
+	af->to_sk_daddr(&to, sk);
+
+	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+	err = sctp_wait_for_connect(asoc, &timeo);
+
+	/* Don't free association on exit. */
+	asoc = NULL;
+
+out_free:
+
+	SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
+		          " kaddrs: %p err: %d\n",
+	                  asoc, kaddrs, err);
+	if (asoc)
+		sctp_association_free(asoc);
+	return err;
+}
+
+/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
+ *
+ * API 8.9
+ * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
+ *
+ * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
+ * If the sd is an IPv6 socket, the addresses passed can either be IPv4
+ * or IPv6 addresses.
+ *
+ * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
+ * Section 3.1.2 for this usage.
+ *
+ * addrs is a pointer to an array of one or more socket addresses. Each
+ * address is contained in its appropriate structure (i.e. struct
+ * sockaddr_in or struct sockaddr_in6) the family of the address type
+ * must be used to distengish the address length (note that this
+ * representation is termed a "packed array" of addresses). The caller
+ * specifies the number of addresses in the array with addrcnt.
+ *
+ * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
+ * -1, and sets errno to the appropriate error code.
+ *
+ * For SCTP, the port given in each socket address must be the same, or
+ * sctp_connectx() will fail, setting errno to EINVAL.
+ *
+ * An application can use sctp_connectx to initiate an association with
+ * an endpoint that is multi-homed.  Much like sctp_bindx() this call
+ * allows a caller to specify multiple addresses at which a peer can be
+ * reached.  The way the SCTP stack uses the list of addresses to set up
+ * the association is implementation dependant.  This function only
+ * specifies that the stack will try to make use of all the addresses in
+ * the list when needed.
+ *
+ * Note that the list of addresses passed in is only used for setting up
+ * the association.  It does not necessarily equal the set of addresses
+ * the peer uses for the resulting association.  If the caller wants to
+ * find out the set of peer addresses, it must use sctp_getpaddrs() to
+ * retrieve them after the association has been set up.
+ *
+ * Basically do nothing but copying the addresses from user to kernel
+ * land and invoking either sctp_connectx(). This is used for tunneling
+ * the sctp_connectx() request through sctp_setsockopt() from userspace.
+ *
+ * We don't use copy_from_user() for optimization: we first do the
+ * sanity checks (buffer size -fast- and access check-healthy
+ * pointer); if all of those succeed, then we can alloc the memory
+ * (expensive operation) needed to copy the data to kernel. Then we do
+ * the copying without checking the user space area
+ * (__copy_from_user()).
+ *
+ * On exit there is no need to do sockfd_put(), sys_setsockopt() does
+ * it.
+ *
+ * sk        The sk of the socket
+ * addrs     The pointer to the addresses in user land
+ * addrssize Size of the addrs buffer
+ *
+ * Returns 0 if ok, <0 errno code on error.
+ */
+SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+				      struct sockaddr __user *addrs,
+				      int addrs_size)
+{
+	int err = 0;
+	struct sockaddr *kaddrs;
+
+	SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
+			  __FUNCTION__, sk, addrs, addrs_size);
+
+	if (unlikely(addrs_size <= 0))
+		return -EINVAL;
+
+	/* Check the user passed a healthy pointer.  */
+	if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
+		return -EFAULT;
+
+	/* Alloc space for the address array in kernel memory.  */
+	kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
+	if (unlikely(!kaddrs))
+		return -ENOMEM;
+
+	if (__copy_from_user(kaddrs, addrs, addrs_size)) {
+		err = -EFAULT;
+	} else {
+		err = __sctp_connect(sk, kaddrs, addrs_size);
+	}
+
+	kfree(kaddrs);
+	return err;
+}
+
 /* API 3.1.4 close() - UDP Style Syntax
  * Applications use close() to perform graceful shutdown (as described in
  * Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -1095,7 +1337,7 @@
 	sp = sctp_sk(sk);
 	ep = sp->ep;
 
-	SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name);
+	SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep);
 
 	/* We cannot send a message over a TCP-style listening socket. */
 	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) {
@@ -1306,7 +1548,7 @@
 		}
 
 		/* Prime the peer's transport structures.  */
-		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
+		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN);
 		if (!transport) {
 			err = -ENOMEM;
 			goto out_free;
@@ -2208,6 +2450,12 @@
 					       optlen, SCTP_BINDX_REM_ADDR);
 		break;
 
+	case SCTP_SOCKOPT_CONNECTX:
+		/* 'optlen' is the size of the addresses buffer. */
+		retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
+					       optlen);
+		break;
+
 	case SCTP_DISABLE_FRAGMENTS:
 		retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);
 		break;
@@ -2283,112 +2531,29 @@
  *
  * len: the size of the address.
  */
-SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
+SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
 			     int addr_len)
 {
-	struct sctp_sock *sp;
-	struct sctp_endpoint *ep;
-	struct sctp_association *asoc;
-	struct sctp_transport *transport;
-	union sctp_addr to;
-	struct sctp_af *af;
-	sctp_scope_t scope;
-	long timeo;
 	int err = 0;
+	struct sctp_af *af;
 
 	sctp_lock_sock(sk);
 
-	SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n",
-			  __FUNCTION__, sk, uaddr, addr_len);
+	SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
+			  __FUNCTION__, sk, addr, addr_len);
 
-	sp = sctp_sk(sk);
-	ep = sp->ep;
-
-	/* connect() cannot be done on a socket that is already in ESTABLISHED
-	 * state - UDP-style peeled off socket or a TCP-style socket that
-	 * is already connected.
-	 * It cannot be done even on a TCP-style listening socket.
-	 */
-	if (sctp_sstate(sk, ESTABLISHED) ||
-	    (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
-		err = -EISCONN;
-		goto out_unlock;
+	/* Validate addr_len before calling common connect/connectx routine. */
+	af = sctp_get_af_specific(addr->sa_family);
+	if (!af || addr_len < af->sockaddr_len) {
+		err = -EINVAL;
+	} else {
+		/* Pass correct addr len to common routine (so it knows there
+		 * is only one address being passed.
+		 */
+		err = __sctp_connect(sk, addr, af->sockaddr_len);
 	}
 
-	err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len);
-	if (err)
-		goto out_unlock;
-
-	if (addr_len > sizeof(to))
-		addr_len = sizeof(to);
-	memcpy(&to, uaddr, addr_len);
-	to.v4.sin_port = ntohs(to.v4.sin_port);
-
-	asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
-	if (asoc) {
-		if (asoc->state >= SCTP_STATE_ESTABLISHED)
-			err = -EISCONN;
-		else
-			err = -EALREADY;
-		goto out_unlock;
-	}
-
-	/* If we could not find a matching association on the endpoint,
-	 * make sure that there is no peeled-off association matching the
-	 * peer address even on another socket.
-	 */
-	if (sctp_endpoint_is_peeled_off(ep, &to)) {
-		err = -EADDRNOTAVAIL;
-		goto out_unlock;
-	}
-
-	/* If a bind() or sctp_bindx() is not called prior to a connect()
-	 * call, the system picks an ephemeral port and will choose an address
-	 * set equivalent to binding with a wildcard address.
-	 */
-	if (!ep->base.bind_addr.port) {
-		if (sctp_autobind(sk)) {
-			err = -EAGAIN;
-			goto out_unlock;
-		}
-	}
-
-	scope = sctp_scope(&to);
-	asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
-	if (!asoc) {
-		err = -ENOMEM;
-		goto out_unlock;
-  	}
-
-	/* Prime the peer's transport structures.  */
-	transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
-	if (!transport) {
-		sctp_association_free(asoc);
-		goto out_unlock;
-	}
-	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
-	if (err < 0) {
-		sctp_association_free(asoc);
-		goto out_unlock;
-	}
-
-	err = sctp_primitive_ASSOCIATE(asoc, NULL);
-	if (err < 0) {
-		sctp_association_free(asoc);
-		goto out_unlock;
-	}
-
-	/* Initialize sk's dport and daddr for getpeername() */
-	inet_sk(sk)->dport = htons(asoc->peer.port);
-	af = sctp_get_af_specific(to.sa.sa_family);
-	af->to_sk_daddr(&to, sk);
-
-	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
-	err = sctp_wait_for_connect(asoc, &timeo);
-
-out_unlock:
 	sctp_release_sock(sk);
-
 	return err;
 }
 
@@ -2677,12 +2842,15 @@
 	/* Map ipv4 address into v4-mapped-on-v6 address.  */
 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
 		(union sctp_addr *)&status.sstat_primary.spinfo_address);
-	status.sstat_primary.spinfo_state = transport->active;
+	status.sstat_primary.spinfo_state = transport->state;
 	status.sstat_primary.spinfo_cwnd = transport->cwnd;
 	status.sstat_primary.spinfo_srtt = transport->srtt;
 	status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
 	status.sstat_primary.spinfo_mtu = transport->pmtu;
 
+	if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
+		status.sstat_primary.spinfo_state = SCTP_ACTIVE;
+
 	if (put_user(len, optlen)) {
 		retval = -EFAULT;
 		goto out;
@@ -2733,12 +2901,15 @@
 		return -EINVAL;
 
 	pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
-	pinfo.spinfo_state = transport->active;
+	pinfo.spinfo_state = transport->state;
 	pinfo.spinfo_cwnd = transport->cwnd;
 	pinfo.spinfo_srtt = transport->srtt;
 	pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
 	pinfo.spinfo_mtu = transport->pmtu;
 
+	if (pinfo.spinfo_state == SCTP_UNKNOWN)
+		pinfo.spinfo_state = SCTP_ACTIVE;
+
 	if (put_user(len, optlen)) {
 		retval = -EFAULT;
 		goto out;
@@ -3591,7 +3762,8 @@
 	int retval = 0;
 	int len;
 
-	SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk);
+	SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n",
+			  sk, optname);
 
 	/* I can hardly begin to describe how wrong this is.  This is
 	 * so broken as to be worse than useless.  The API draft
@@ -4596,8 +4768,7 @@
 	return err;
 
 do_error:
-	if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
-					 	asoc->max_init_attempts)
+	if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
 		err = -ETIMEDOUT;
 	else
 		err = -ECONNREFUSED;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index f30882e..0ec0fde 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -83,7 +83,9 @@
 	peer->last_time_used = jiffies;
 	peer->last_time_ecne_reduced = jiffies;
 
-	peer->active = SCTP_ACTIVE;
+	peer->init_sent_count = 0;
+
+	peer->state = SCTP_ACTIVE;
 	peer->hb_allowed = 0;
 
 	/* Initialize the default path max_retrans.  */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 0a42607..d65ed86 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -118,7 +118,6 @@
 	xfrm_policy_put_afinfo(afinfo);
 	return type;
 }
-EXPORT_SYMBOL(xfrm_get_type);
 
 int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
 		    unsigned short family)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 2537f26..9d206c2 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1055,6 +1055,43 @@
 }
 
 EXPORT_SYMBOL(xfrm_state_mtu);
+
+int xfrm_init_state(struct xfrm_state *x)
+{
+	struct xfrm_state_afinfo *afinfo;
+	int family = x->props.family;
+	int err;
+
+	err = -EAFNOSUPPORT;
+	afinfo = xfrm_state_get_afinfo(family);
+	if (!afinfo)
+		goto error;
+
+	err = 0;
+	if (afinfo->init_flags)
+		err = afinfo->init_flags(x);
+
+	xfrm_state_put_afinfo(afinfo);
+
+	if (err)
+		goto error;
+
+	err = -EPROTONOSUPPORT;
+	x->type = xfrm_get_type(x->id.proto, family);
+	if (x->type == NULL)
+		goto error;
+
+	err = x->type->init_state(x);
+	if (err)
+		goto error;
+
+	x->km.state = XFRM_STATE_VALID;
+
+error:
+	return err;
+}
+
+EXPORT_SYMBOL(xfrm_init_state);
  
 void __init xfrm_state_init(void)
 {
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 5ce8558..ecade48 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -249,17 +249,10 @@
 	if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
 		goto error;
 
-	err = -ENOENT;
-	x->type = xfrm_get_type(x->id.proto, x->props.family);
-	if (x->type == NULL)
-		goto error;
-
-	err = x->type->init_state(x, NULL);
+	err = xfrm_init_state(x);
 	if (err)
 		goto error;
 
-	x->curlft.add_time = (unsigned long) xtime.tv_sec;
-	x->km.state = XFRM_STATE_VALID;
 	x->km.seq = p->seq;
 
 	return x;