## Automatically generated incremental diff
## From:   linux-2.5.65-bk4
## To:     linux-2.5.65-bk5
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.65-bk4/CREDITS linux-2.5.65-bk5/CREDITS
--- linux-2.5.65-bk4/CREDITS	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/CREDITS	Mon Mar 31 12:44:32 2003
@@ -1840,10 +1840,10 @@
 S: Germany
 
 N: Achim Leubner
-E: achim@vortex.de
-D: GDT SCSI Disk Array Controller driver
-S: ICP vortex Computersysteme GmbH
-S: Flein
+E: achim.leubner@intel.com
+D: GDT Disk Array Controller/Storage RAID controller driver
+S: ICP vortex GmbH, an Intel company
+S: Neckarsulm
 S: Germany
 
 N: Phil Lewis
diff -urN linux-2.5.65-bk4/Makefile linux-2.5.65-bk5/Makefile
--- linux-2.5.65-bk4/Makefile	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/Makefile	Mon Mar 31 12:44:32 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 65
-EXTRAVERSION = -bk4
+EXTRAVERSION = -bk5
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.65-bk4/arch/i386/boot98/Makefile linux-2.5.65-bk5/arch/i386/boot98/Makefile
--- linux-2.5.65-bk4/arch/i386/boot98/Makefile	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/i386/boot98/Makefile	Mon Mar 31 12:44:32 2003
@@ -25,9 +25,8 @@
 
 #RAMDISK := -DRAMDISK=512
 
-EXTRA_TARGETS	:= vmlinux.bin bootsect bootsect.o \
-		   setup setup.o zImage bzImage
-
+targets		:= vmlinux.bin bootsect bootsect.o setup setup.o \
+		   zImage bzImage
 subdir- 	:= compressed
 
 host-progs	:= tools/build
@@ -62,8 +61,36 @@
 	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
 					IMAGE_OFFSET=$(IMAGE_OFFSET) $@
 
-zdisk: $(BOOTIMAGE)
-	dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+FDARGS = 
+
+$(obj)/mtools.conf: $(src)/mtools.conf.in
+	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
+
+# This requires write access to /dev/fd0
+zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
+	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
+	syslinux /dev/fd0					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
+
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
+	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
+	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
+	syslinux $(obj)/fdimage					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
+
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
+	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
+	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
+	syslinux $(obj)/fdimage					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
 
 zlilo: $(BOOTIMAGE)
 	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -urN linux-2.5.65-bk4/arch/i386/boot98/compressed/Makefile linux-2.5.65-bk5/arch/i386/boot98/compressed/Makefile
--- linux-2.5.65-bk4/arch/i386/boot98/compressed/Makefile	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/i386/boot98/compressed/Makefile	Mon Mar 31 12:44:32 2003
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-EXTRA_TARGETS	:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
 EXTRA_AFLAGS	:= -traditional
 
 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
diff -urN linux-2.5.65-bk4/arch/i386/boot98/mtools.conf.in linux-2.5.65-bk5/arch/i386/boot98/mtools.conf.in
--- linux-2.5.65-bk4/arch/i386/boot98/mtools.conf.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/arch/i386/boot98/mtools.conf.in	Mon Mar 31 12:44:32 2003
@@ -0,0 +1,17 @@
+#
+# mtools configuration file for "make (b)zdisk"
+#
+
+# Actual floppy drive
+drive a:
+  file="/dev/fd0"
+
+# 1.44 MB floppy disk image
+drive v:
+  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
+
+# 2.88 MB floppy disk image (mostly for virtual uses)
+drive w:
+  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
+
+
diff -urN linux-2.5.65-bk4/arch/i386/boot98/tools/build.c linux-2.5.65-bk5/arch/i386/boot98/tools/build.c
--- linux-2.5.65-bk4/arch/i386/boot98/tools/build.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/i386/boot98/tools/build.c	Mon Mar 31 12:44:32 2003
@@ -149,13 +149,10 @@
 	sz = sb.st_size;
 	fprintf (stderr, "System is %d kB\n", sz/1024);
 	sys_size = (sz + 15) / 16;
-	/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
-	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+	/* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
+	if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
 		die("System is too big. Try using %smodules.",
 			is_big_kernel ? "" : "bzImage or ");
-	if (sys_size > 0xefff)
-		fprintf(stderr,"warning: kernel is too big for standalone boot "
-		    "from floppy\n");
 	while (sz > 0) {
 		int l, n;
 
diff -urN linux-2.5.65-bk4/arch/i386/lib/usercopy.c linux-2.5.65-bk5/arch/i386/lib/usercopy.c
--- linux-2.5.65-bk4/arch/i386/lib/usercopy.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/i386/lib/usercopy.c	Mon Mar 31 12:44:32 2003
@@ -51,18 +51,18 @@
 } while (0)
 
 /**
- * __strncpy_from_user: - Copy a NULL terminated string from userspace, with less checking.
+ * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
  * @dst:   Destination address, in kernel space.  This buffer must be at
  *         least @count bytes long.
  * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NULL.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
  * 
- * Copies a NULL-terminated string from userspace to kernel space.
+ * Copies a NUL-terminated string from userspace to kernel space.
  * Caller must check the specified block with access_ok() before calling
  * this function.
  *
  * On success, returns the length of the string (not including the trailing
- * NULL).
+ * NUL).
  *
  * If access to userspace fails, returns -EFAULT (some data may have been
  * copied).
@@ -79,16 +79,16 @@
 }
 
 /**
- * strncpy_from_user: - Copy a NULL terminated string from userspace.
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
  * @dst:   Destination address, in kernel space.  This buffer must be at
  *         least @count bytes long.
  * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NULL.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
  * 
- * Copies a NULL-terminated string from userspace to kernel space.
+ * Copies a NUL-terminated string from userspace to kernel space.
  *
  * On success, returns the length of the string (not including the trailing
- * NULL).
+ * NUL).
  *
  * If access to userspace fails, returns -EFAULT (some data may have been
  * copied).
@@ -172,9 +172,9 @@
  * @s: The string to measure.
  * @n: The maximum valid length
  *
- * Get the size of a NULL-terminated string in user space.
+ * Get the size of a NUL-terminated string in user space.
  *
- * Returns the size of the string INCLUDING the terminating NULL.
+ * Returns the size of the string INCLUDING the terminating NUL.
  * On exception, returns 0.
  * If the string is too long, returns a value greater than @n.
  */
diff -urN linux-2.5.65-bk4/arch/ia64/ia32/sys_ia32.c linux-2.5.65-bk5/arch/ia64/ia32/sys_ia32.c
--- linux-2.5.65-bk4/arch/ia64/ia32/sys_ia32.c	Mon Mar 17 13:44:11 2003
+++ linux-2.5.65-bk5/arch/ia64/ia32/sys_ia32.c	Mon Mar 31 12:44:32 2003
@@ -3124,38 +3124,17 @@
 	compat_gid_t	ex32_anon_gid;
 };
 
-struct nfsctl_uidmap32 {
-	u32			ug32_ident;   /* char * */
-	compat_uid_t	ug32_uidbase;
-	s32			ug32_uidlen;
-	u32			ug32_udimap;  /* uid_t * */
-	compat_uid_t	ug32_gidbase;
-	s32			ug32_gidlen;
-	u32			ug32_gdimap;  /* gid_t * */
-};
-
-struct nfsctl_fhparm32 {
-	struct sockaddr		gf32_addr;
-	compat_dev_t	gf32_dev;
-	compat_ino_t	gf32_ino;
-	s32			gf32_version;
-};
-
 struct nfsctl_arg32 {
 	s32			ca32_version;	/* safeguard */
 	union {
 		struct nfsctl_svc32	u32_svc;
 		struct nfsctl_client32	u32_client;
 		struct nfsctl_export32	u32_export;
-		struct nfsctl_uidmap32	u32_umap;
-		struct nfsctl_fhparm32	u32_getfh;
 		u32			u32_debug;
 	} u;
 #define ca32_svc	u.u32_svc
 #define ca32_client	u.u32_client
 #define ca32_export	u.u32_export
-#define ca32_umap	u.u32_umap
-#define ca32_getfh	u.u32_getfh
 #define ca32_authd	u.u32_authd
 #define ca32_debug	u.u32_debug
 };
@@ -3227,75 +3206,6 @@
 }
 
 static int
-nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	u32 uaddr;
-	int i;
-	int err;
-
-	memset(karg, 0, sizeof(*karg));
-	if(__get_user(karg->ca_version, &arg32->ca32_version))
-		return -EFAULT;
-	karg->ca_umap.ug_ident = (char *)get_zeroed_page(GFP_USER);
-	if(!karg->ca_umap.ug_ident)
-		return -ENOMEM;
-	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
-	if(strncpy_from_user(karg->ca_umap.ug_ident,
-			     (char *)A(uaddr), PAGE_SIZE) <= 0)
-		return -EFAULT;
-	err |= __get_user(karg->ca_umap.ug_uidbase,
-		      &arg32->ca32_umap.ug32_uidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_uidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) *
-					   karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_udimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_udimap[i],
-			      &(((compat_uid_t *)A(uaddr))[i]));
-	err |= __get_user(karg->ca_umap.ug_gidbase,
-		      &arg32->ca32_umap.ug32_gidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_gidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) *
-					   karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_gdimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_gdimap[i],
-			      &(((compat_gid_t *)A(uaddr))[i]));
-
-	return err;
-}
-
-static int
-nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	int err;
-
-	err = __get_user(karg->ca_version, &arg32->ca32_version);
-	err |= copy_from_user(&karg->ca_getfh.gf_addr,
-			  &arg32->ca32_getfh.gf32_addr,
-			  (sizeof(struct sockaddr)));
-	err |= __get_user(karg->ca_getfh.gf_dev,
-		      &arg32->ca32_getfh.gf32_dev);
-	err |= __get_user(karg->ca_getfh.gf_ino,
-		      &arg32->ca32_getfh.gf32_ino);
-	err |= __get_user(karg->ca_getfh.gf_version,
-		      &arg32->ca32_getfh.gf32_version);
-	return err;
-}
-
-static int
 nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
 {
 	int err;
@@ -3340,13 +3250,6 @@
 	case NFSCTL_EXPORT:
 		err = nfs_exp32_trans(karg, arg32);
 		break;
-	/* This one is unimplemented, be we're ready for it. */
-	case NFSCTL_UGIDUPDATE:
-		err = nfs_uud32_trans(karg, arg32);
-		break;
-	case NFSCTL_GETFH:
-		err = nfs_getfh32_trans(karg, arg32);
-		break;
 	default:
 		err = -EINVAL;
 		break;
@@ -3358,21 +3261,12 @@
 	err = sys_nfsservctl(cmd, karg, kres);
 	set_fs(oldfs);
 
-	if(!err && cmd == NFSCTL_GETFH)
+	if(!err && cmd == NFSCTL_GETFS)
 		err = nfs_getfh32_res_trans(kres, res32);
 
 done:
-	if(karg) {
-		if(cmd == NFSCTL_UGIDUPDATE) {
-			if(karg->ca_umap.ug_ident)
-				kfree(karg->ca_umap.ug_ident);
-			if(karg->ca_umap.ug_udimap)
-				kfree(karg->ca_umap.ug_udimap);
-			if(karg->ca_umap.ug_gdimap)
-				kfree(karg->ca_umap.ug_gdimap);
-		}
+	if(karg)
 		kfree(karg);
-	}
 	if(kres)
 		kfree(kres);
 	return err;
diff -urN linux-2.5.65-bk4/arch/parisc/kernel/sys_parisc32.c linux-2.5.65-bk5/arch/parisc/kernel/sys_parisc32.c
--- linux-2.5.65-bk4/arch/parisc/kernel/sys_parisc32.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk5/arch/parisc/kernel/sys_parisc32.c	Mon Mar 31 12:44:32 2003
@@ -1282,25 +1282,6 @@
 	__kernel_gid_t	ex_anon_gid;
 };
 
-/* GETFH */
-struct nfsctl_fhparm32 {
-	struct sockaddr	gf_addr;
-	__kernel_dev_t	gf_dev;
-	compat_ino_t	gf_ino;
-	int		gf_version;
-};
-
-/* UGIDUPDATE */
-struct nfsctl_uidmap32 {
-	compat_caddr_t	ug_ident;
-	__kernel_uid_t	ug_uidbase;
-	int		ug_uidlen;
-	compat_caddr_t	ug_udimap;
-	__kernel_gid_t	ug_gidbase;
-	int		ug_gidlen;
-	compat_caddr_t	ug_gdimap;
-};
-
 struct nfsctl_arg32 {
 	int			ca_version;	/* safeguard */
 	/* wide kernel places this union on 8-byte boundary, narrow on 4 */
@@ -1308,8 +1289,6 @@
 		struct nfsctl_svc	u_svc;
 		struct nfsctl_client	u_client;
 		struct nfsctl_export32	u_export;
-		struct nfsctl_uidmap32	u_umap;
-		struct nfsctl_fhparm32	u_getfh;
 		struct nfsctl_fdparm	u_getfd;
 		struct nfsctl_fsparm	u_getfs;
 	} u;
@@ -1346,29 +1325,6 @@
 		ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfs);
 		break;
 
-	case NFSCTL_GETFH:		/* nfsctl_fhparm */
-		ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_getfh);
-#undef CP
-#define CP(x)	n.u.u_getfh.gf_##x = n32.u.u_getfh.gf_##x
-		CP(addr);
-		CP(dev);
-		CP(ino);
-		CP(version);
-		break;
-
-	case NFSCTL_UGIDUPDATE:		/* nfsctl_uidmap */
-		ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_umap);
-#undef CP
-#define CP(x)	n.u.u_umap.ug_##x = n32.u.u_umap.ug_##x
-		n.u.u_umap.ug_ident = (char *)(u_long)n32.u.u_umap.ug_ident;
-		CP(uidbase);
-		CP(uidlen);
-		n.u.u_umap.ug_udimap = (__kernel_uid_t *)(u_long)n32.u.u_umap.ug_udimap;
-		CP(gidbase);
-		CP(gidlen);
-		n.u.u_umap.ug_gdimap = (__kernel_gid_t *)(u_long)n32.u.u_umap.ug_gdimap;
-		break;
-
 	case NFSCTL_UNEXPORT:		/* nfsctl_export */
 	case NFSCTL_EXPORT:		/* nfsctl_export */
 		ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_export);
@@ -1393,7 +1349,7 @@
 	if (ret == 0) {
 		unsigned char rbuf[NFS_FHSIZE + sizeof (struct knfsd_fh)];
 		KERNEL_SYSCALL(ret, sys_nfsservctl, cmd, &n, &rbuf);
-		if (cmd == NFSCTL_GETFH || cmd == NFSCTL_GETFD) {
+		if (cmd == NFSCTL_GETFD) {
 			ret = copy_to_user(resp, rbuf, NFS_FHSIZE);
 		} else if (cmd == NFSCTL_GETFS) {
 			ret = copy_to_user(resp, rbuf, sizeof (struct knfsd_fh));
diff -urN linux-2.5.65-bk4/arch/ppc64/kernel/sys_ppc32.c linux-2.5.65-bk5/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.5.65-bk4/arch/ppc64/kernel/sys_ppc32.c	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk5/arch/ppc64/kernel/sys_ppc32.c	Mon Mar 31 12:44:32 2003
@@ -884,23 +884,6 @@
 	compat_gid_t	ex32_anon_gid;
 };
 
-struct nfsctl_uidmap32 {
-	u32			ug32_ident;   /* char * */
-	compat_uid_t	ug32_uidbase;
-	s32			ug32_uidlen;
-	u32			ug32_udimap;  /* uid_t * */
-	compat_uid_t	ug32_gidbase;
-	s32			ug32_gidlen;
-	u32			ug32_gdimap;  /* gid_t * */
-};
-
-struct nfsctl_fhparm32 {
-	struct sockaddr		gf32_addr;
-	compat_dev_t	gf32_dev;
-	compat_ino_t	gf32_ino;
-	s32			gf32_version;
-};
-
 struct nfsctl_fdparm32 {
 	struct sockaddr		gd32_addr;
 	s8			gd32_path[NFS_MAXPATHLEN+1];
@@ -919,16 +902,12 @@
 		struct nfsctl_svc32	u32_svc;
 		struct nfsctl_client32	u32_client;
 		struct nfsctl_export32	u32_export;
-		struct nfsctl_uidmap32	u32_umap;
-		struct nfsctl_fhparm32	u32_getfh;
 		struct nfsctl_fdparm32	u32_getfd;
 		struct nfsctl_fsparm32	u32_getfs;
 	} u;
 #define ca32_svc	u.u32_svc
 #define ca32_client	u.u32_client
 #define ca32_export	u.u32_export
-#define ca32_umap	u.u32_umap
-#define ca32_getfh	u.u32_getfh
 #define ca32_getfd	u.u32_getfd
 #define ca32_getfs	u.u32_getfs
 #define ca32_authd	u.u32_authd
@@ -1001,73 +980,6 @@
 	return 0;
 }
 
-static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	u32 uaddr;
-	int i;
-	int err;
-
-	memset(karg, 0, sizeof(*karg));
-	if(__get_user(karg->ca_version, &arg32->ca32_version))
-		return -EFAULT;
-	karg->ca_umap.ug_ident = (char *)get_zeroed_page(GFP_USER);
-	if(!karg->ca_umap.ug_ident)
-		return -ENOMEM;
-	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
-	if(strncpy_from_user(karg->ca_umap.ug_ident,
-			     (char *)A(uaddr), PAGE_SIZE) <= 0)
-		return -EFAULT;
-	err |= __get_user(karg->ca_umap.ug_uidbase,
-		      &arg32->ca32_umap.ug32_uidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_uidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_udimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_udimap[i],
-			      &(((compat_uid_t *)A(uaddr))[i]));
-	err |= __get_user(karg->ca_umap.ug_gidbase,
-		      &arg32->ca32_umap.ug32_gidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_gidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_gdimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_gdimap[i],
-			      &(((compat_gid_t *)A(uaddr))[i]));
-
-	return err;
-}
-
-static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	int err;
-	
-	err = __get_user(karg->ca_version, &arg32->ca32_version);
-	err |= copy_from_user(&karg->ca_getfh.gf_addr,
-			  &arg32->ca32_getfh.gf32_addr,
-			  (sizeof(struct sockaddr)));
-	err |= __get_user(karg->ca_getfh.gf_dev,
-		      &arg32->ca32_getfh.gf32_dev);
-	err |= __get_user(karg->ca_getfh.gf_ino,
-		      &arg32->ca32_getfh.gf32_ino);
-	err |= __get_user(karg->ca_getfh.gf_version,
-		      &arg32->ca32_getfh.gf32_version);
-
-	if(err) return -EFAULT;
-	return 0;
-}
-
 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
@@ -1154,13 +1066,6 @@
 	case NFSCTL_UNEXPORT:
 		err = nfs_exp32_trans(karg, arg32);
 		break;
-	/* This one is unimplemented, be we're ready for it. */
-	case NFSCTL_UGIDUPDATE:
-		err = nfs_uud32_trans(karg, arg32);
-		break;
-	case NFSCTL_GETFH:
-		err = nfs_getfh32_trans(karg, arg32);
-		break;
 	case NFSCTL_GETFD:
 		err = nfs_getfd32_trans(karg, arg32);
 		break;
@@ -1181,23 +1086,13 @@
 	if (err)
 		goto done;
 
-	if((cmd == NFSCTL_GETFH) ||
-	   (cmd == NFSCTL_GETFD) ||
+	if((cmd == NFSCTL_GETFD) ||
 	   (cmd == NFSCTL_GETFS))
 		err = nfs_getfh32_res_trans(kres, res32);
 
 done:
-	if(karg) {
-		if(cmd == NFSCTL_UGIDUPDATE) {
-			if(karg->ca_umap.ug_ident)
-				kfree(karg->ca_umap.ug_ident);
-			if(karg->ca_umap.ug_udimap)
-				kfree(karg->ca_umap.ug_udimap);
-			if(karg->ca_umap.ug_gdimap)
-				kfree(karg->ca_umap.ug_gdimap);
-		}
+	if(karg)
 		kfree(karg);
-	}
 	if(kres)
 		kfree(kres);
 	return err;
diff -urN linux-2.5.65-bk4/arch/s390x/kernel/linux32.c linux-2.5.65-bk5/arch/s390x/kernel/linux32.c
--- linux-2.5.65-bk4/arch/s390x/kernel/linux32.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/arch/s390x/kernel/linux32.c	Mon Mar 31 12:44:32 2003
@@ -2092,23 +2092,6 @@
 	compat_gid_t	ex32_anon_gid;
 };
 
-struct nfsctl_uidmap32 {
-	u32			ug32_ident;   /* char * */
-	compat_uid_t	ug32_uidbase;
-	s32			ug32_uidlen;
-	u32			ug32_udimap;  /* uid_t * */
-	compat_uid_t	ug32_gidbase;
-	s32			ug32_gidlen;
-	u32			ug32_gdimap;  /* gid_t * */
-};
-
-struct nfsctl_fhparm32 {
-	struct sockaddr		gf32_addr;
-	compat_dev_t	gf32_dev;
-	compat_ino_t	gf32_ino;
-	s32			gf32_version;
-};
-
 struct nfsctl_fdparm32 {
 	struct sockaddr		gd32_addr;
 	s8			gd32_path[NFS_MAXPATHLEN+1];
@@ -2127,16 +2110,12 @@
 		struct nfsctl_svc32	u32_svc;
 		struct nfsctl_client32	u32_client;
 		struct nfsctl_export32	u32_export;
-		struct nfsctl_uidmap32	u32_umap;
-		struct nfsctl_fhparm32	u32_getfh;
 		struct nfsctl_fdparm32	u32_getfd;
 		struct nfsctl_fsparm32	u32_getfs;
 	} u;
 #define ca32_svc	u.u32_svc
 #define ca32_client	u.u32_client
 #define ca32_export	u.u32_export
-#define ca32_umap	u.u32_umap
-#define ca32_getfh	u.u32_getfh
 #define ca32_getfd	u.u32_getfd
 #define ca32_getfs	u.u32_getfs
 #define ca32_authd	u.u32_authd
@@ -2205,71 +2184,6 @@
 	return err;
 }
 
-static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	u32 uaddr;
-	int i;
-	int err;
-
-	memset(karg, 0, sizeof(*karg));
-	if(__get_user(karg->ca_version, &arg32->ca32_version))
-		return -EFAULT;
-	karg->ca_umap.ug_ident = (char *)get_zeroed_page(GFP_USER);
-	if(!karg->ca_umap.ug_ident)
-		return -ENOMEM;
-	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
-	if(strncpy_from_user(karg->ca_umap.ug_ident,
-			     (char *)A(uaddr), PAGE_SIZE) <= 0)
-		return -EFAULT;
-	err |= __get_user(karg->ca_umap.ug_uidbase,
-		      &arg32->ca32_umap.ug32_uidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_uidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_udimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_udimap[i],
-			      &(((compat_uid_t *)A(uaddr))[i]));
-	err |= __get_user(karg->ca_umap.ug_gidbase,
-		      &arg32->ca32_umap.ug32_gidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_gidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_gdimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_gdimap[i],
-			      &(((compat_gid_t *)A(uaddr))[i]));
-
-	return err;
-}
-
-static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	int err;
-	
-	err = __get_user(karg->ca_version, &arg32->ca32_version);
-	err |= copy_from_user(&karg->ca_getfh.gf_addr,
-			  &arg32->ca32_getfh.gf32_addr,
-			  (sizeof(struct sockaddr)));
-	err |= __get_user(karg->ca_getfh.gf_dev,
-		      &arg32->ca32_getfh.gf32_dev);
-	err |= __get_user(karg->ca_getfh.gf_ino,
-		      &arg32->ca32_getfh.gf32_ino);
-	err |= __get_user(karg->ca_getfh.gf_version,
-		      &arg32->ca32_getfh.gf32_version);
-	return err;
-}
-
 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
@@ -2345,13 +2259,6 @@
 	case NFSCTL_UNEXPORT:
 		err = nfs_exp32_trans(karg, arg32);
 		break;
-	/* This one is unimplemented, be we're ready for it. */
-	case NFSCTL_UGIDUPDATE:
-		err = nfs_uud32_trans(karg, arg32);
-		break;
-	case NFSCTL_GETFH:
-		err = nfs_getfh32_trans(karg, arg32);
-		break;
 	case NFSCTL_GETFD:
 		err = nfs_getfd32_trans(karg, arg32);
 		break;
@@ -2372,23 +2279,13 @@
 	if (err)
 		goto done;
 
-	if((cmd == NFSCTL_GETFH) ||
-	   (cmd == NFSCTL_GETFD) ||
+	if((cmd == NFSCTL_GETFD) ||
 	   (cmd == NFSCTL_GETFS))
 		err = nfs_getfh32_res_trans(kres, res32);
 
 done:
-	if(karg) {
-		if(cmd == NFSCTL_UGIDUPDATE) {
-			if(karg->ca_umap.ug_ident)
-				kfree(karg->ca_umap.ug_ident);
-			if(karg->ca_umap.ug_udimap)
-				kfree(karg->ca_umap.ug_udimap);
-			if(karg->ca_umap.ug_gdimap)
-				kfree(karg->ca_umap.ug_gdimap);
-		}
+	if(karg)
 		kfree(karg);
-	}
 	if(kres)
 		kfree(kres);
 	return err;
diff -urN linux-2.5.65-bk4/arch/sparc64/kernel/sparc64_ksyms.c linux-2.5.65-bk5/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.5.65-bk4/arch/sparc64/kernel/sparc64_ksyms.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/sparc64/kernel/sparc64_ksyms.c	Mon Mar 31 12:44:32 2003
@@ -21,6 +21,7 @@
 #include <linux/fs_struct.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
+#include <net/compat.h>
 
 #include <asm/oplib.h>
 #include <asm/delay.h>
diff -urN linux-2.5.65-bk4/arch/sparc64/kernel/sys_sparc32.c linux-2.5.65-bk5/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.5.65-bk4/arch/sparc64/kernel/sys_sparc32.c	Mon Mar 17 13:44:15 2003
+++ linux-2.5.65-bk5/arch/sparc64/kernel/sys_sparc32.c	Mon Mar 31 12:44:32 2003
@@ -2234,23 +2234,6 @@
 	compat_gid_t	ex32_anon_gid;
 };
 
-struct nfsctl_uidmap32 {
-	u32			ug32_ident;   /* char * */
-	compat_uid_t	ug32_uidbase;
-	s32			ug32_uidlen;
-	u32			ug32_udimap;  /* uid_t * */
-	compat_uid_t	ug32_gidbase;
-	s32			ug32_gidlen;
-	u32			ug32_gdimap;  /* gid_t * */
-};
-
-struct nfsctl_fhparm32 {
-	struct sockaddr		gf32_addr;
-	compat_dev_t	gf32_dev;
-	compat_ino_t	gf32_ino;
-	s32			gf32_version;
-};
-
 struct nfsctl_fdparm32 {
 	struct sockaddr		gd32_addr;
 	s8			gd32_path[NFS_MAXPATHLEN+1];
@@ -2269,16 +2252,12 @@
 		struct nfsctl_svc32	u32_svc;
 		struct nfsctl_client32	u32_client;
 		struct nfsctl_export32	u32_export;
-		struct nfsctl_uidmap32	u32_umap;
-		struct nfsctl_fhparm32	u32_getfh;
 		struct nfsctl_fdparm32	u32_getfd;
 		struct nfsctl_fsparm32	u32_getfs;
 	} u;
 #define ca32_svc	u.u32_svc
 #define ca32_client	u.u32_client
 #define ca32_export	u.u32_export
-#define ca32_umap	u.u32_umap
-#define ca32_getfh	u.u32_getfh
 #define ca32_getfd	u.u32_getfd
 #define ca32_getfs	u.u32_getfs
 #define ca32_authd	u.u32_authd
@@ -2347,71 +2326,6 @@
 	return (err ? -EFAULT : 0);
 }
 
-static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	u32 uaddr;
-	int i;
-	int err;
-
-	memset(karg, 0, sizeof(*karg));
-	if(__get_user(karg->ca_version, &arg32->ca32_version))
-		return -EFAULT;
-	karg->ca_umap.ug_ident = (char *)get_zeroed_page(GFP_USER);
-	if(!karg->ca_umap.ug_ident)
-		return -ENOMEM;
-	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
-	if(strncpy_from_user(karg->ca_umap.ug_ident,
-			     (char *)A(uaddr), PAGE_SIZE) <= 0)
-		return -EFAULT;
-	err |= __get_user(karg->ca_umap.ug_uidbase,
-		      &arg32->ca32_umap.ug32_uidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_uidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_udimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_udimap[i],
-			      &(((compat_uid_t *)A(uaddr))[i]));
-	err |= __get_user(karg->ca_umap.ug_gidbase,
-		      &arg32->ca32_umap.ug32_gidbase);
-	err |= __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_gidlen);
-	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
-	if (err)
-		return -EFAULT;
-	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
-					  GFP_USER);
-	if(!karg->ca_umap.ug_gdimap)
-		return -ENOMEM;
-	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
-		err |= __get_user(karg->ca_umap.ug_gdimap[i],
-			      &(((compat_gid_t *)A(uaddr))[i]));
-
-	return (err ? -EFAULT : 0);
-}
-
-static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	int err;
-	
-	err = __get_user(karg->ca_version, &arg32->ca32_version);
-	err |= copy_from_user(&karg->ca_getfh.gf_addr,
-			  &arg32->ca32_getfh.gf32_addr,
-			  (sizeof(struct sockaddr)));
-	err |= __get_user(karg->ca_getfh.gf_dev,
-		      &arg32->ca32_getfh.gf32_dev);
-	err |= __get_user(karg->ca_getfh.gf_ino,
-		      &arg32->ca32_getfh.gf32_ino);
-	err |= __get_user(karg->ca_getfh.gf_version,
-		      &arg32->ca32_getfh.gf32_version);
-	return (err ? -EFAULT : 0);
-}
-
 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
@@ -2483,13 +2397,6 @@
 	case NFSCTL_UNEXPORT:
 		err = nfs_exp32_trans(karg, arg32);
 		break;
-	/* This one is unimplemented, be we're ready for it. */
-	case NFSCTL_UGIDUPDATE:
-		err = nfs_uud32_trans(karg, arg32);
-		break;
-	case NFSCTL_GETFH:
-		err = nfs_getfh32_trans(karg, arg32);
-		break;
 	case NFSCTL_GETFD:
 		err = nfs_getfd32_trans(karg, arg32);
 		break;
@@ -2510,23 +2417,13 @@
 	if (err)
 		goto done;
 
-	if((cmd == NFSCTL_GETFH) ||
-	   (cmd == NFSCTL_GETFD) ||
+	if((cmd == NFSCTL_GETFD) ||
 	   (cmd == NFSCTL_GETFS))
 		err = nfs_getfh32_res_trans(kres, res32);
 
 done:
-	if(karg) {
-		if(cmd == NFSCTL_UGIDUPDATE) {
-			if(karg->ca_umap.ug_ident)
-				kfree(karg->ca_umap.ug_ident);
-			if(karg->ca_umap.ug_udimap)
-				kfree(karg->ca_umap.ug_udimap);
-			if(karg->ca_umap.ug_gdimap)
-				kfree(karg->ca_umap.ug_gdimap);
-		}
+	if(karg)
 		kfree(karg);
-	}
 	if(kres)
 		kfree(kres);
 	return err;
diff -urN linux-2.5.65-bk4/arch/sparc64/kernel/sys_sunos32.c linux-2.5.65-bk5/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.5.65-bk4/arch/sparc64/kernel/sys_sunos32.c	Mon Mar 17 13:44:11 2003
+++ linux-2.5.65-bk5/arch/sparc64/kernel/sys_sunos32.c	Mon Mar 31 12:44:32 2003
@@ -56,6 +56,7 @@
 /* For SOCKET_I */
 #include <linux/socket.h>
 #include <net/sock.h>
+#include <net/compat.h>
 
 /* Use this to get at 32-bit user passed pointers. */
 #define A(__x)				\
diff -urN linux-2.5.65-bk4/arch/sparc64/solaris/socket.c linux-2.5.65-bk5/arch/sparc64/solaris/socket.c
--- linux-2.5.65-bk4/arch/sparc64/solaris/socket.c	Mon Mar 17 13:44:19 2003
+++ linux-2.5.65-bk5/arch/sparc64/solaris/socket.c	Mon Mar 31 12:44:32 2003
@@ -15,6 +15,7 @@
 #include <linux/file.h>
 #include <linux/net.h>
 #include <linux/compat.h>
+#include <net/compat.h>
 
 #include <asm/uaccess.h>
 #include <asm/string.h>
diff -urN linux-2.5.65-bk4/arch/um/drivers/line.c linux-2.5.65-bk5/arch/um/drivers/line.c
--- linux-2.5.65-bk4/arch/um/drivers/line.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk5/arch/um/drivers/line.c	Mon Mar 31 12:44:32 2003
@@ -438,7 +438,7 @@
 
 	from = line_driver->symlink_from;
 	to = line_driver->symlink_to;
-	err = devfs_mk_symlink(NULL, from, 0, to, NULL, NULL);
+	err = devfs_mk_symlink(from, to);
 	if(err) printk("Symlink creation from /dev/%s to /dev/%s "
 		       "returned %d\n", from, to, err);
 
diff -urN linux-2.5.65-bk4/arch/um/drivers/mmapper_kern.c linux-2.5.65-bk5/arch/um/drivers/mmapper_kern.c
--- linux-2.5.65-bk4/arch/um/drivers/mmapper_kern.c	Mon Mar 17 13:43:42 2003
+++ linux-2.5.65-bk5/arch/um/drivers/mmapper_kern.c	Mon Mar 31 12:44:32 2003
@@ -127,8 +127,7 @@
 	devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, 
 			30, 0, S_IFCHR | S_IRUGO | S_IWUGO, 
 			&mmapper_fops, NULL); 
-	devfs_mk_symlink(NULL, "mmapper0", DEVFS_FL_DEFAULT, "mmapper",
-			 NULL, NULL);
+	devfs_mk_symlink("mmapper0", "mmapper");
 	return(0);
 }
 
diff -urN linux-2.5.65-bk4/arch/um/drivers/ubd_kern.c linux-2.5.65-bk5/arch/um/drivers/ubd_kern.c
--- linux-2.5.65-bk4/arch/um/drivers/ubd_kern.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/um/drivers/ubd_kern.c	Mon Mar 31 12:44:32 2003
@@ -488,7 +488,7 @@
 			struct gendisk **disk_out, devfs_handle_t dir_handle,
 			devfs_handle_t *handle_out)
 {
-	char devfs_name[sizeof("nnnnnn\0")];
+	char devfs_name[sizeof("ubd/nnnnnn\0")];
 	struct gendisk *disk;
 	int minor = unit << UBD_SHIFT;
 
@@ -505,8 +505,8 @@
 	*disk_out = disk;
 
 	/* /dev/ubd/N style names */
-	sprintf(devfs_name, "%d", unit);
-	*handle_out = devfs_register(dir_handle, devfs_name,
+	sprintf(devfs_name, "ubd/%d", unit);
+	*handle_out = devfs_register(NULL, devfs_name,
 				     0, major, minor,
 				     S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
 				     S_IWGRP, &ubd_blops, NULL);
@@ -682,7 +682,7 @@
 {
         int i;
 
-	ubd_dir_handle = devfs_mk_dir(NULL, "ubd", NULL);
+	ubd_dir_handle = devfs_mk_dir("ubd");
 	if (register_blkdev(MAJOR_NR, "ubd"))
 		return -1;
 
@@ -693,7 +693,7 @@
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
-		ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL);
+		ubd_fake_dir_handle = devfs_mk_dir(name);
 		if (register_blkdev(fake_major, "ubd"))
 			return -1;
 	}
diff -urN linux-2.5.65-bk4/arch/x86_64/ia32/sys_ia32.c linux-2.5.65-bk5/arch/x86_64/ia32/sys_ia32.c
--- linux-2.5.65-bk4/arch/x86_64/ia32/sys_ia32.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/arch/x86_64/ia32/sys_ia32.c	Mon Mar 31 12:44:32 2003
@@ -1807,23 +1807,6 @@
 	compat_gid_t	ex32_anon_gid;
 };
 
-struct nfsctl_uidmap32 {
-	u32			ug32_ident;   /* char * */
-	compat_pid_t	ug32_uidbase;
-	s32			ug32_uidlen;
-	u32			ug32_udimap;  /* uid_t * */
-	compat_pid_t	ug32_gidbase;
-	s32			ug32_gidlen;
-	u32			ug32_gdimap;  /* gid_t * */
-};
-
-struct nfsctl_fhparm32 {
-	struct sockaddr		gf32_addr;
-	compat_dev_t	gf32_dev;
-	compat_ino_t	gf32_ino;
-	s32			gf32_version;
-};
-
 struct nfsctl_fdparm32 {
 	struct sockaddr		gd32_addr;
 	s8			gd32_path[NFS_MAXPATHLEN+1];
@@ -1842,16 +1825,12 @@
 		struct nfsctl_svc32	u32_svc;
 		struct nfsctl_client32	u32_client;
 		struct nfsctl_export32	u32_export;
-		struct nfsctl_uidmap32	u32_umap;
-		struct nfsctl_fhparm32	u32_getfh;
 		struct nfsctl_fdparm32	u32_getfd;
 		struct nfsctl_fsparm32	u32_getfs;
 	} u;
 #define ca32_svc	u.u32_svc
 #define ca32_client	u.u32_client
 #define ca32_export	u.u32_export
-#define ca32_umap	u.u32_umap
-#define ca32_getfh	u.u32_getfh
 #define ca32_getfd	u.u32_getfd
 #define ca32_getfs	u.u32_getfs
 #define ca32_authd	u.u32_authd
@@ -1920,22 +1899,6 @@
 	return err;
 }
 
-static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
-	int err;
-	
-	err = get_user(karg->ca_version, &arg32->ca32_version);
-	err |= copy_from_user(&karg->ca_getfh.gf_addr,
-			  &arg32->ca32_getfh.gf32_addr,
-			  (sizeof(struct sockaddr)));
-	err |= __get_user(karg->ca_getfh.gf_dev,
-		      &arg32->ca32_getfh.gf32_dev);
-	err |= __get_user(karg->ca_getfh.gf_ino,
-		      &arg32->ca32_getfh.gf32_ino);
-	err |= __get_user(karg->ca_getfh.gf_version,
-		      &arg32->ca32_getfh.gf32_version);
-	return err;
-}
 
 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
@@ -2008,9 +1971,6 @@
 	case NFSCTL_UNEXPORT:
 		err = nfs_exp32_trans(karg, arg32);
 		break;
-	case NFSCTL_GETFH:
-		err = nfs_getfh32_trans(karg, arg32);
-		break;
 	case NFSCTL_GETFD:
 		err = nfs_getfd32_trans(karg, arg32);
 		break;
@@ -2031,23 +1991,13 @@
 	if (err)
 		goto done;
 
-	if((cmd == NFSCTL_GETFH) ||
-	   (cmd == NFSCTL_GETFD) ||
+	if((cmd == NFSCTL_GETFD) ||
 	   (cmd == NFSCTL_GETFS))
 		err = nfs_getfh32_res_trans(kres, res32);
 
 done:
-	if(karg) {
-		if(cmd == NFSCTL_UGIDUPDATE) {
-			if(karg->ca_umap.ug_ident)
-				kfree(karg->ca_umap.ug_ident);
-			if(karg->ca_umap.ug_udimap)
-				kfree(karg->ca_umap.ug_udimap);
-			if(karg->ca_umap.ug_gdimap)
-				kfree(karg->ca_umap.ug_gdimap);
-		}
+	if(karg)
 		kfree(karg);
-	}
 	if(kres)
 		kfree(kres);
 	return err;
diff -urN linux-2.5.65-bk4/crypto/aes.c linux-2.5.65-bk5/crypto/aes.c
--- linux-2.5.65-bk4/crypto/aes.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk5/crypto/aes.c	Mon Mar 31 12:44:32 2003
@@ -55,6 +55,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/errno.h>
 #include <linux/crypto.h>
 #include <asm/byteorder.h>
 
diff -urN linux-2.5.65-bk4/crypto/api.c linux-2.5.65-bk5/crypto/api.c
--- linux-2.5.65-bk4/crypto/api.c	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk5/crypto/api.c	Mon Mar 31 12:44:32 2003
@@ -15,6 +15,7 @@
  */
 #include <linux/init.h>
 #include <linux/crypto.h>
+#include <linux/errno.h>
 #include <linux/rwsem.h>
 #include <linux/slab.h>
 #include "internal.h"
@@ -151,10 +152,7 @@
 
 void crypto_free_tfm(struct crypto_tfm *tfm)
 {
-	if (crypto_tfm_alg_type(tfm) == CRYPTO_ALG_TYPE_CIPHER)
-		if (tfm->crt_cipher.cit_iv)
-			kfree(tfm->crt_cipher.cit_iv);
-	
+	crypto_exit_ops(tfm);
 	crypto_alg_put(tfm->__crt_alg);
 	kfree(tfm);
 }
diff -urN linux-2.5.65-bk4/crypto/des.c linux-2.5.65-bk5/crypto/des.c
--- linux-2.5.65-bk4/crypto/des.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk5/crypto/des.c	Mon Mar 31 12:44:32 2003
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/errno.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
 
diff -urN linux-2.5.65-bk4/crypto/digest.c linux-2.5.65-bk5/crypto/digest.c
--- linux-2.5.65-bk4/crypto/digest.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/crypto/digest.c	Mon Mar 31 12:44:32 2003
@@ -13,6 +13,7 @@
  */
 #include <linux/crypto.h>
 #include <linux/mm.h>
+#include <linux/errno.h>
 #include <linux/highmem.h>
 #include <asm/scatterlist.h>
 #include "internal.h"
diff -urN linux-2.5.65-bk4/crypto/serpent.c linux-2.5.65-bk5/crypto/serpent.c
--- linux-2.5.65-bk4/crypto/serpent.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk5/crypto/serpent.c	Mon Mar 31 12:44:32 2003
@@ -13,6 +13,7 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/errno.h>
 #include <asm/byteorder.h>
 #include <linux/crypto.h>
 
diff -urN linux-2.5.65-bk4/crypto/twofish.c linux-2.5.65-bk5/crypto/twofish.c
--- linux-2.5.65-bk4/crypto/twofish.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk5/crypto/twofish.c	Mon Mar 31 12:44:32 2003
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/errno.h>
 #include <linux/crypto.h>
 
 
diff -urN linux-2.5.65-bk4/drivers/atm/idt77105.c linux-2.5.65-bk5/drivers/atm/idt77105.c
--- linux-2.5.65-bk4/drivers/atm/idt77105.c	Mon Mar 17 13:44:10 2003
+++ linux-2.5.65-bk5/drivers/atm/idt77105.c	Mon Mar 31 12:44:32 2003
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/atm_idt77105.h>
+#include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
@@ -38,6 +39,7 @@
         unsigned char old_mcr;          /* storage of MCR reg while signal lost */
 };
 
+static spinlock_t idt77105_priv_lock = SPIN_LOCK_UNLOCKED;
 
 #define PRIV(dev) ((struct idt77105_priv *) dev->phy_data)
 
@@ -144,12 +146,11 @@
 	unsigned long flags;
 	struct idt77105_stats stats;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&idt77105_priv_lock, flags);
 	memcpy(&stats, &PRIV(dev)->stats, sizeof(struct idt77105_stats));
 	if (zero)
 		memset(&PRIV(dev)->stats, 0, sizeof(struct idt77105_stats));
-	restore_flags(flags);
+	spin_unlock_irqrestore(&idt77105_priv_lock, flags);
 	if (arg == NULL)
 		return 0;
 	return copy_to_user(arg, &PRIV(dev)->stats,
@@ -267,11 +268,10 @@
 	if (!(PRIV(dev) = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
 		return -ENOMEM;
 	PRIV(dev)->dev = dev;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&idt77105_priv_lock, flags);
 	PRIV(dev)->next = idt77105_all;
 	idt77105_all = PRIV(dev);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&idt77105_priv_lock, flags);
 	memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
         
         /* initialise dev->signal from Good Signal Bit */
@@ -305,11 +305,9 @@
 	idt77105_stats_timer_func(0); /* clear 77105 counters */
 	(void) fetch_stats(dev,NULL,1); /* clear kernel counters */
         
-	cli();
-	if (!start_timer) restore_flags(flags);
-	else {
+	spin_lock_irqsave(&idt77105_priv_lock, flags);
+	if (start_timer) {
 		start_timer = 0;
-		restore_flags(flags);
                 
 		init_timer(&stats_timer);
 		stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD;
@@ -321,32 +319,11 @@
 		restart_timer.function = idt77105_restart_timer_func;
 		add_timer(&restart_timer);
 	}
+	spin_unlock_irqrestore(&idt77105_priv_lock, flags);
 	return 0;
 }
 
 
-static const struct atmphy_ops idt77105_ops = {
-	idt77105_start,
-	idt77105_ioctl,
-	idt77105_int
-};
-
-
-int __init idt77105_init(struct atm_dev *dev)
-{
-	MOD_INC_USE_COUNT;
-
-	dev->phy = &idt77105_ops;
-	return 0;
-}
-
-
-/*
- * TODO: this function should be called through phy_ops
- * but that will not be possible for some time as there is
- * currently a freeze on modifying that structure
- * -- Greg Banks, 13 Sep 1999
- */
 int idt77105_stop(struct atm_dev *dev)
 {
 	struct idt77105_priv *walk, *prev;
@@ -372,30 +349,33 @@
             }
         }
 
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
 
+static const struct atmphy_ops idt77105_ops = {
+	.start = 	idt77105_start,
+	.ioctl =	idt77105_ioctl,
+	.interrupt =	idt77105_int,
+	.stop =		idt77105_stop,
+};
 
-EXPORT_SYMBOL(idt77105_init);
-EXPORT_SYMBOL(idt77105_stop);
-
-MODULE_LICENSE("GPL");
-
-#ifdef MODULE
 
-int init_module(void)
+int idt77105_init(struct atm_dev *dev)
 {
+	dev->phy = &idt77105_ops;
 	return 0;
 }
 
+EXPORT_SYMBOL(idt77105_init);
 
-void cleanup_module(void)
+static void __exit idt77105_exit(void)
 {
         /* turn off timers */
         del_timer(&stats_timer);
         del_timer(&restart_timer);
 }
 
-#endif
+module_exit(idt77105_exit);
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.65-bk4/drivers/atm/nicstar.c linux-2.5.65-bk5/drivers/atm/nicstar.c
--- linux-2.5.65-bk4/drivers/atm/nicstar.c	Mon Mar 17 13:43:47 2003
+++ linux-2.5.65-bk5/drivers/atm/nicstar.c	Mon Mar 31 12:44:32 2003
@@ -354,11 +354,8 @@
 
       card = cards[i];
 
-#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
-      if (card->max_pcr == ATM_25_PCR) {
-        idt77105_stop(card->atmdev);
-      }
-#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
+      if (card->atmdev->phy && card->atmdev->phy->stop)
+        card->atmdev->phy->stop(card->atmdev);
 
       /* Stop everything */
       writel(0x00000000, card->membase + CFG);
@@ -490,11 +487,6 @@
    card->atmdev = NULL;
    card->pcidev = pcidev;
    card->membase = pci_resource_start(pcidev, 1);
-#ifdef __powerpc__
-   /* Compensate for different memory map between host CPU and PCI bus.
-      Shouldn't we use a macro for this? */
-   card->membase += KERNELBASE;
-#endif /* __powerpc__ */
    card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE);
    if (card->membase == 0)
    {
@@ -905,22 +897,13 @@
    card->atmdev->phy = NULL;
 
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
-   if (card->max_pcr == ATM_OC3_PCR) {
+   if (card->max_pcr == ATM_OC3_PCR)
       suni_init(card->atmdev);
-
-      MOD_INC_USE_COUNT;
-      /* Can't remove the nicstar driver or the suni driver would oops */
-   }
 #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
 
 #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
-   if (card->max_pcr == ATM_25_PCR) {
+   if (card->max_pcr == ATM_25_PCR)
       idt77105_init(card->atmdev);
-      /* Note that for the IDT77105 PHY we don't need the awful
-       * module count hack that the SUNI needs because we can
-       * stop the '105 when the nicstar module is cleaned up.
-       */
-   }
 #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
 
    if (card->atmdev->phy && card->atmdev->phy->start)
@@ -2327,6 +2310,7 @@
          {
             push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data),
                         0, 0);
+            atomic_inc(&vcc->stats->rx_drop);
          }
          else
 	 {
@@ -2354,6 +2338,7 @@
             {
                push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
                            0, 0);
+               atomic_inc(&vcc->stats->rx_drop);
             }
             else
 	    {
@@ -2378,6 +2363,7 @@
             {
                push_rxbufs(card, BUF_LG, (u32) skb,
                            (u32) virt_to_bus(skb->data), 0, 0);
+               atomic_inc(&vcc->stats->rx_drop);
             }
             else
             {
@@ -2462,6 +2448,7 @@
             }
 	    else
 	       dev_kfree_skb_any(hb);
+	    atomic_inc(&vcc->stats->rx_drop);
          }
          else
 	 {
diff -urN linux-2.5.65-bk4/drivers/atm/suni.c linux-2.5.65-bk5/drivers/atm/suni.c
--- linux-2.5.65-bk4/drivers/atm/suni.c	Mon Mar 17 13:44:40 2003
+++ linux-2.5.65-bk5/drivers/atm/suni.c	Mon Mar 31 12:44:32 2003
@@ -297,7 +297,7 @@
 	mri = GET(MRI); /* reset SUNI */
 	PUT(mri | SUNI_MRI_RESET,MRI);
 	PUT(mri,MRI);
-	PUT(0,MT); /* disable all tests */
+	PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */
 	REG_CHANGE(SUNI_TPOP_APM_S,SUNI_TPOP_APM_S_SHIFT,SUNI_TPOP_S_SONET,
 	    TPOP_APM); /* use SONET */
 	REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP,
@@ -307,24 +307,6 @@
 	return 0;
 }
 
-
 EXPORT_SYMBOL(suni_init);
 
-
 MODULE_LICENSE("GPL");
-
-#ifdef MODULE
-
-
-int init_module(void)
-{
-	return 0;
-}
-
-
-void cleanup_module(void)
-{
-	/* Nay */
-}
-
-#endif
diff -urN linux-2.5.65-bk4/drivers/atm/suni.h linux-2.5.65-bk5/drivers/atm/suni.h
--- linux-2.5.65-bk4/drivers/atm/suni.h	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk5/drivers/atm/suni.h	Mon Mar 31 12:44:32 2003
@@ -198,6 +198,7 @@
 #define SUNI_MT_IOTST		0x04	/* RW, enable test mode */
 #define SUNI_MT_DBCTRL		0x08	/* W, control data bus by CSB pin */
 #define SUNI_MT_PMCTST		0x10	/* W, PMC test mode */
+#define SUNI_MT_DS27_53		0x80	/* RW, select between 8- or 16- bit */
 
 
 #define SUNI_IDLE_PATTERN       0x6a    /* idle pattern */
diff -urN linux-2.5.65-bk4/drivers/block/Kconfig linux-2.5.65-bk5/drivers/block/Kconfig
--- linux-2.5.65-bk4/drivers/block/Kconfig	Mon Mar 17 13:43:47 2003
+++ linux-2.5.65-bk5/drivers/block/Kconfig	Mon Mar 31 12:44:32 2003
@@ -6,6 +6,7 @@
 
 config BLK_DEV_FD
 	tristate "Normal floppy disk support"
+	depends on !X86_PC9800
 	---help---
 	  If you want to use the floppy disk drive(s) of your PC under Linux,
 	  say Y. Information about this driver, especially important for IBM
diff -urN linux-2.5.65-bk4/drivers/block/acsi_slm.c linux-2.5.65-bk5/drivers/block/acsi_slm.c
--- linux-2.5.65-bk4/drivers/block/acsi_slm.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk5/drivers/block/acsi_slm.c	Mon Mar 31 12:44:32 2003
@@ -1006,7 +1006,7 @@
 	BufferP = SLMBuffer;
 	SLMState = IDLE;
 	
-	devfs_mk_dir (NULL, "slm", NULL);
+	devfs_mk_dir("slm");
 	for (i = 0; i < MAX_SLM; i++) {
 		char name[16];
 		sprintf(name, "slm/%d", i);
diff -urN linux-2.5.65-bk4/drivers/block/cpqarray.c linux-2.5.65-bk5/drivers/block/cpqarray.c
--- linux-2.5.65-bk4/drivers/block/cpqarray.c	Mon Mar 17 13:43:42 2003
+++ linux-2.5.65-bk5/drivers/block/cpqarray.c	Mon Mar 31 12:44:32 2003
@@ -1679,9 +1679,8 @@
 
 				}
 				if (!disk->de) {
-					char txt[16];
-					sprintf(txt,"ida/c%dd%d",ctlr,log_unit);
-					disk->de = devfs_mk_dir(NULL,txt,NULL);
+					disk->de = devfs_mk_dir("ida/c%dd%d",
+							ctlr, log_unit);
 				}
 				info_p->phys_drives =
 				    sense_config_buf->ctlr_phys_drv;
diff -urN linux-2.5.65-bk4/drivers/block/floppy.c linux-2.5.65-bk5/drivers/block/floppy.c
--- linux-2.5.65-bk4/drivers/block/floppy.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/block/floppy.c	Mon Mar 31 12:44:32 2003
@@ -4233,7 +4233,7 @@
 			goto Enomem;
 	}
 
-	devfs_mk_dir (NULL, "floppy", NULL);
+	devfs_mk_dir ("floppy");
 	if (register_blkdev(FLOPPY_MAJOR,"fd")) {
 		err = -EBUSY;
 		goto out;
diff -urN linux-2.5.65-bk4/drivers/block/ll_rw_blk.c linux-2.5.65-bk5/drivers/block/ll_rw_blk.c
--- linux-2.5.65-bk4/drivers/block/ll_rw_blk.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/block/ll_rw_blk.c	Mon Mar 31 12:44:32 2003
@@ -26,6 +26,7 @@
 #include <linux/bootmem.h>	/* for max_pfn/max_low_pfn */
 #include <linux/completion.h>
 #include <linux/slab.h>
+#include <linux/swap.h>
 
 static void blk_unplug_work(void *data);
 static void blk_unplug_timeout(unsigned long data);
@@ -200,6 +201,7 @@
 	q->make_request_fn = mfn;
 	q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
 	q->backing_dev_info.state = 0;
+	q->backing_dev_info.memory_backed = 0;
 	blk_queue_max_sectors(q, MAX_SECTORS);
 	blk_queue_hardsect_size(q, 512);
 	blk_queue_dma_alignment(q, 511);
diff -urN linux-2.5.65-bk4/drivers/block/loop.c linux-2.5.65-bk5/drivers/block/loop.c
--- linux-2.5.65-bk4/drivers/block/loop.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk5/drivers/block/loop.c	Mon Mar 31 12:44:32 2003
@@ -1020,7 +1020,7 @@
 	if (register_blkdev(LOOP_MAJOR, "loop"))
 		return -EIO;
 
-	devfs_mk_dir(NULL, "loop", NULL);
+	devfs_mk_dir("loop");
 
 	loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL);
 	if (!loop_dev)
diff -urN linux-2.5.65-bk4/drivers/block/nbd.c linux-2.5.65-bk5/drivers/block/nbd.c
--- linux-2.5.65-bk4/drivers/block/nbd.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/block/nbd.c	Mon Mar 31 12:44:32 2003
@@ -565,7 +565,7 @@
 	printk("nbd: registered device at major %d\n", NBD_MAJOR);
 #endif
 	blk_init_queue(&nbd_queue, do_nbd_request, &nbd_lock);
-	devfs_mk_dir (NULL, "nbd", NULL);
+	devfs_mk_dir("nbd");
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
 		char name[16];
diff -urN linux-2.5.65-bk4/drivers/block/paride/pg.c linux-2.5.65-bk5/drivers/block/paride/pg.c
--- linux-2.5.65-bk4/drivers/block/paride/pg.c	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk5/drivers/block/paride/pg.c	Mon Mar 31 12:44:32 2003
@@ -642,7 +642,7 @@
 		  if (PG.present) pi_release(PI);
 		return -1;
 	}
-	devfs_mk_dir (NULL, "pg", NULL);
+	devfs_mk_dir ("pg");
 	for (unit=0; unit<PG_UNITS; unit++)
 		if (PG.present) {
 			char name[16];
diff -urN linux-2.5.65-bk4/drivers/block/paride/pt.c linux-2.5.65-bk5/drivers/block/paride/pt.c
--- linux-2.5.65-bk4/drivers/block/paride/pt.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk5/drivers/block/paride/pt.c	Mon Mar 31 12:44:32 2003
@@ -913,7 +913,7 @@
 		return -1;
 	}
 
-	devfs_mk_dir (NULL, "pt", NULL);
+	devfs_mk_dir ("pt");
 	for (unit=0;unit<PT_UNITS;unit++)
 		if (PT.present) {
 			char name[16];
diff -urN linux-2.5.65-bk4/drivers/block/rd.c linux-2.5.65-bk5/drivers/block/rd.c
--- linux-2.5.65-bk4/drivers/block/rd.c	Mon Mar 17 13:44:11 2003
+++ linux-2.5.65-bk5/drivers/block/rd.c	Mon Mar 31 12:44:32 2003
@@ -416,7 +416,7 @@
 
 	blk_queue_make_request(&rd_queue, &rd_make_request);
 
-	devfs_mk_dir (NULL, "rd", NULL);
+	devfs_mk_dir("rd");
 
 	for (i = 0; i < NUM_RAMDISKS; i++) {
 		struct gendisk *disk = rd_disks[i];
diff -urN linux-2.5.65-bk4/drivers/block/swim3.c linux-2.5.65-bk5/drivers/block/swim3.c
--- linux-2.5.65-bk4/drivers/block/swim3.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/drivers/block/swim3.c	Mon Mar 31 12:44:32 2003
@@ -979,7 +979,7 @@
 	int err = -ENOMEM;
 	int i;
 
-	floppy_devfs_handle = devfs_mk_dir(NULL, "floppy", NULL);
+	floppy_devfs_handle = devfs_mk_dir("floppy");
 
 	swim = find_devices("floppy");
 	while (swim && (floppy_count < MAX_FLOPPIES))
@@ -1095,9 +1095,9 @@
 
 	printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
 		mediabay ? "in media bay" : "");
-	sprintf(floppy_name, "%s%d", floppy_devfs_handle ? "" : "floppy",
-			floppy_count);
-	floppy_handle = devfs_register(floppy_devfs_handle, floppy_name, 
+
+	sprintf(floppy_name, "floppy/%d", floppy_count);
+	floppy_handle = devfs_register(NULL, floppy_name, 
 			DEVFS_FL_DEFAULT, FLOPPY_MAJOR, floppy_count, 
 			S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, 
 			&floppy_fops, NULL);
diff -urN linux-2.5.65-bk4/drivers/block/umem.c linux-2.5.65-bk5/drivers/block/umem.c
--- linux-2.5.65-bk4/drivers/block/umem.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk5/drivers/block/umem.c	Mon Mar 31 12:44:32 2003
@@ -1154,7 +1154,8 @@
 		if (!mm_gendisk[i])
 			goto out;
 	}
-	devfs_mk_dir(NULL, "umem", NULL);
+
+	devfs_mk_dir("umem");
 
 	for (i = 0; i < num_cards; i++) {
 		struct gendisk *disk = mm_gendisk[i];
diff -urN linux-2.5.65-bk4/drivers/block/xd.c linux-2.5.65-bk5/drivers/block/xd.c
--- linux-2.5.65-bk4/drivers/block/xd.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk5/drivers/block/xd.c	Mon Mar 31 12:44:32 2003
@@ -173,7 +173,7 @@
 	if (register_blkdev(XT_DISK_MAJOR, "xd"))
 		goto out1;
 
-	devfs_mk_dir(NULL, "xd", NULL);
+	devfs_mk_dir("xd");
 	blk_init_queue(&xd_queue, do_xd_request, &xd_lock);
 	if (xd_detect(&controller,&address)) {
 
diff -urN linux-2.5.65-bk4/drivers/cdrom/sbpcd.c linux-2.5.65-bk5/drivers/cdrom/sbpcd.c
--- linux-2.5.65-bk4/drivers/cdrom/sbpcd.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk5/drivers/cdrom/sbpcd.c	Mon Mar 31 12:44:32 2003
@@ -5805,7 +5805,7 @@
 
 	blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock);
 
-	devfs_mk_dir (NULL, "sbp", NULL);
+	devfs_mk_dir("sbp");
 
 	for (j=0;j<NR_SBPCD;j++)
 	{
diff -urN linux-2.5.65-bk4/drivers/char/ipmi/ipmi_devintf.c linux-2.5.65-bk5/drivers/char/ipmi/ipmi_devintf.c
--- linux-2.5.65-bk4/drivers/char/ipmi/ipmi_devintf.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/char/ipmi/ipmi_devintf.c	Mon Mar 31 12:44:32 2003
@@ -444,15 +444,14 @@
 
 static void ipmi_new_smi(int if_num)
 {
-	char name[2];
+	char name[10];
 
 	if (if_num > MAX_DEVICES)
 		return;
 
-	name[0] = if_num + '0';
-	name[1] = '\0';
+	snprinf(name, sizeof(name), "ipmidev/%d", if_num);
 
-	handles[if_num] = devfs_register(devfs_handle, name, DEVFS_FL_NONE,
+	handles[if_num] = devfs_register(NULL, name, DEVFS_FL_NONE,
 					 ipmi_major, if_num,
 					 S_IFCHR | S_IRUSR | S_IWUSR,
 					 &ipmi_fops, NULL);
@@ -489,7 +488,7 @@
 		ipmi_major = rv;
 	}
 
-	devfs_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
+	devfs_handle = devfs_mk_dir(DEVICE_NAME);
 
 	rv = ipmi_smi_watcher_register(&smi_watcher);
 	if (rv) {
diff -urN linux-2.5.65-bk4/drivers/char/istallion.c linux-2.5.65-bk5/drivers/char/istallion.c
--- linux-2.5.65-bk4/drivers/char/istallion.c	Mon Mar 17 13:44:12 2003
+++ linux-2.5.65-bk5/drivers/char/istallion.c	Mon Mar 31 12:44:32 2003
@@ -5334,7 +5334,7 @@
 		printk(KERN_ERR "STALLION: failed to register serial memory "
 				"device\n");
 
-	devfs_mk_dir (NULL, "staliomem", NULL);
+	devfs_mk_dir("staliomem");
 	for (i = 0; i < 4; i++) {
 		char name[16];
 		sprintf(name, "staliomem/%d", i);
diff -urN linux-2.5.65-bk4/drivers/char/lp.c linux-2.5.65-bk5/drivers/char/lp.c
--- linux-2.5.65-bk4/drivers/char/lp.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/drivers/char/lp.c	Mon Mar 31 12:44:32 2003
@@ -906,7 +906,7 @@
 		return -EIO;
 	}
 
-	devfs_mk_dir (NULL, "printers", NULL);
+	devfs_mk_dir("printers");
 
 	if (parport_register_driver (&lp_driver)) {
 		printk (KERN_ERR "lp: unable to register with parport\n");
diff -urN linux-2.5.65-bk4/drivers/char/misc.c linux-2.5.65-bk5/drivers/char/misc.c
--- linux-2.5.65-bk4/drivers/char/misc.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk5/drivers/char/misc.c	Mon Mar 31 12:44:32 2003
@@ -196,7 +196,7 @@
 	if (misc->minor < DYNAMIC_MINORS)
 		misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
 	if (!devfs_handle)
-		devfs_handle = devfs_mk_dir (NULL, "misc", NULL);
+		devfs_handle = devfs_mk_dir("misc");
 	dir = strchr (misc->name, '/') ? NULL : devfs_handle;
 	misc->devfs_handle =
 		devfs_register (dir, misc->name, DEVFS_FL_NONE,
diff -urN linux-2.5.65-bk4/drivers/char/ppdev.c linux-2.5.65-bk5/drivers/char/ppdev.c
--- linux-2.5.65-bk4/drivers/char/ppdev.c	Mon Mar 17 13:44:48 2003
+++ linux-2.5.65-bk5/drivers/char/ppdev.c	Mon Mar 31 12:44:32 2003
@@ -758,7 +758,7 @@
 			PP_MAJOR);
 		return -EIO;
 	}
-	devfs_mk_dir (NULL, "parports", NULL);
+	devfs_mk_dir("parports");
 	for (i = 0; i < PARPORT_MAX; i++) {
 		char name[16];
 		sprintf(name, "parports/%d", i);
diff -urN linux-2.5.65-bk4/drivers/char/pty.c linux-2.5.65-bk5/drivers/char/pty.c
--- linux-2.5.65-bk4/drivers/char/pty.c	Mon Mar 17 13:43:51 2003
+++ linux-2.5.65-bk5/drivers/char/pty.c	Mon Mar 31 12:44:32 2003
@@ -432,7 +432,7 @@
 
 	/* Unix98 devices */
 #ifdef CONFIG_UNIX98_PTYS
-	devfs_mk_dir (NULL, "pts", NULL);
+	devfs_mk_dir("pts");
 	printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS);
 	for ( i = 0 ; i < UNIX98_NR_MAJORS ; i++ ) {
 		int j;
diff -urN linux-2.5.65-bk4/drivers/char/stallion.c linux-2.5.65-bk5/drivers/char/stallion.c
--- linux-2.5.65-bk4/drivers/char/stallion.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk5/drivers/char/stallion.c	Mon Mar 31 12:44:32 2003
@@ -3213,7 +3213,7 @@
  */
 	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
 		printk("STALLION: failed to register serial board device\n");
-	devfs_mk_dir (NULL, "staliomem", NULL);
+	devfs_mk_dir("staliomem");
 	for (i = 0; i < 4; i++) {
 		char name[16];
 		sprintf(name, "staliomem/%d", i);
diff -urN linux-2.5.65-bk4/drivers/char/tipar.c linux-2.5.65-bk5/drivers/char/tipar.c
--- linux-2.5.65-bk4/drivers/char/tipar.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/drivers/char/tipar.c	Mon Mar 31 12:44:32 2003
@@ -490,7 +490,7 @@
 	}
 
 	/* Use devfs with tree: /dev/ticables/par/[0..2] */
-	devfs_mk_dir(NULL, "ticables/par", NULL);
+	devfs_mk_dir("ticables/par");
 
 	if (parport_register_driver(&tipar_driver)) {
 		printk("tipar: unable to register with parport\n");
diff -urN linux-2.5.65-bk4/drivers/i2c/i2c-dev.c linux-2.5.65-bk5/drivers/i2c/i2c-dev.c
--- linux-2.5.65-bk4/drivers/i2c/i2c-dev.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk5/drivers/i2c/i2c-dev.c	Mon Mar 31 12:44:33 2003
@@ -436,7 +436,7 @@
 		       I2C_MAJOR);
 		return -EIO;
 	}
-	devfs_mk_dir(NULL, "i2c", NULL);
+	devfs_mk_dir("i2c");
 	if ((res = i2c_add_driver(&i2cdev_driver))) {
 		printk(KERN_ERR "i2c-dev.o: Driver registration failed, module not inserted.\n");
 		devfs_remove("i2c");
diff -urN linux-2.5.65-bk4/drivers/ide/Kconfig linux-2.5.65-bk5/drivers/ide/Kconfig
--- linux-2.5.65-bk4/drivers/ide/Kconfig	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk5/drivers/ide/Kconfig	Mon Mar 31 12:44:33 2003
@@ -44,7 +44,25 @@
 
 config BLK_DEV_HD_IDE
 	bool "Use old disk-only driver on primary interface"
-	depends on BLK_DEV_IDE && X86
+	depends on BLK_DEV_IDE && X86 && X86_PC9800!=y
+	---help---
+	  There are two drivers for MFM/RLL/IDE disks.  Most people use just
+	  the new enhanced driver by itself.  This option however installs the
+	  old hard disk driver to control the primary IDE/disk interface in
+	  the system, leaving the new enhanced IDE driver to take care of only
+	  the 2nd/3rd/4th IDE interfaces.  Doing this will prevent you from
+	  having an IDE/ATAPI CD-ROM or tape drive connected to the primary
+	  IDE interface.  Choosing this option may be useful for older systems
+	  which have MFM/RLL/ESDI controller+drives at the primary port
+	  address (0x1f0), along with IDE drives at the secondary/3rd/4th port
+	  addresses.
+
+	  Normally, just say N here; you will then use the new driver for all
+	  4 interfaces.
+
+config BLK_DEV_HD_IDE98
+	bool "Use old disk-only driver on primary interface"
+	depends on BLK_DEV_IDE && X86 && X86_PC9800
 	---help---
 	  There are two drivers for MFM/RLL/IDE disks.  Most people use just
 	  the new enhanced driver by itself.  This option however installs the
diff -urN linux-2.5.65-bk4/drivers/ide/ide-iops.c linux-2.5.65-bk5/drivers/ide/ide-iops.c
--- linux-2.5.65-bk4/drivers/ide/ide-iops.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/ide/ide-iops.c	Mon Mar 31 12:44:33 2003
@@ -902,7 +902,7 @@
         /*
          * Select the drive, and issue the SETFEATURES command
          */
-	disable_irq(hwif->irq);	/* disable_irq_nosync ?? */
+	disable_irq_nosync(hwif->irq);
 	udelay(1);
 	SELECT_DRIVE(drive);
 	SELECT_MASK(drive, 0);
diff -urN linux-2.5.65-bk4/drivers/ide/ide-probe.c linux-2.5.65-bk5/drivers/ide/ide-probe.c
--- linux-2.5.65-bk4/drivers/ide/ide-probe.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/ide/ide-probe.c	Mon Mar 31 12:44:33 2003
@@ -1304,7 +1304,7 @@
 			hwif->channel, unit, drive->lun);
 		if (drive->present) {
 			device_register(&drive->gendev);
-			drive->de = devfs_mk_dir(NULL, name, NULL);
+			drive->de = devfs_mk_dir(name);
 		}
 	}
 	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
diff -urN linux-2.5.65-bk4/drivers/ide/ide.c linux-2.5.65-bk5/drivers/ide/ide.c
--- linux-2.5.65-bk4/drivers/ide/ide.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/ide/ide.c	Mon Mar 31 12:44:33 2003
@@ -2392,6 +2392,8 @@
 int ide_register_driver(ide_driver_t *driver)
 {
 	struct list_head list;
+	struct list_head *list_loop;
+	struct list_head *tmp_storage;
 
 	spin_lock(&drivers_lock);
 	list_add(&driver->drivers, &drivers);
@@ -2402,8 +2404,8 @@
 	list_splice_init(&ata_unused, &list);
 	spin_unlock(&drives_lock);
 
-	while (!list_empty(&list)) {
-		ide_drive_t *drive = list_entry(list.next, ide_drive_t, list);
+	list_for_each_safe(list_loop, tmp_storage, &list) {
+		ide_drive_t *drive = container_of(list_loop, ide_drive_t, list);
 		list_del_init(&drive->list);
 		if (drive->present)
 			ata_attach(drive);
@@ -2470,7 +2472,7 @@
 	static char banner_printed;
 	if (!banner_printed) {
 		printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
-		devfs_mk_dir(NULL, "ide", NULL);
+		devfs_mk_dir("ide");
 		system_bus_speed = ide_system_bus_speed();
 		banner_printed = 1;
 	}
diff -urN linux-2.5.65-bk4/drivers/ide/legacy/Makefile linux-2.5.65-bk5/drivers/ide/legacy/Makefile
--- linux-2.5.65-bk4/drivers/ide/legacy/Makefile	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/ide/legacy/Makefile	Mon Mar 31 12:44:33 2003
@@ -16,10 +16,7 @@
 obj-$(CONFIG_BLK_DEV_IDECS)		+= ide-cs.o
 
 # Last of all
-ifneq ($(CONFIG_X86_PC9800),y)
 obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
-else
-obj-$(CONFIG_BLK_DEV_HD)		+= hd98.o
-endif
+obj-$(CONFIG_BLK_DEV_HD98)		+= hd98.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff -urN linux-2.5.65-bk4/drivers/ieee1394/dv1394.c linux-2.5.65-bk5/drivers/ieee1394/dv1394.c
--- linux-2.5.65-bk4/drivers/ieee1394/dv1394.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/drivers/ieee1394/dv1394.c	Mon Mar 31 12:44:33 2003
@@ -177,15 +177,6 @@
 
 static struct hpsb_highlevel *hl_handle; /* = NULL; */
 
-static LIST_HEAD(dv1394_devfs);
-struct dv1394_devfs_entry {
-	struct list_head list;
-    devfs_handle_t devfs;
-	char name[32];
-	struct dv1394_devfs_entry *parent;
-};
-static spinlock_t dv1394_devfs_lock = SPIN_LOCK_UNLOCKED;
-
 /* translate from a struct file* to the corresponding struct video_card* */
 
 static inline struct video_card* file_to_video_card(struct file *file)
@@ -2456,137 +2447,25 @@
 };
 
 
-/*** DEVFS HELPERS *********************************************************/
-
-struct dv1394_devfs_entry *
-dv1394_devfs_find( char *name)
-{
-	struct list_head *lh;
-	struct dv1394_devfs_entry *p;
-
-	spin_lock( &dv1394_devfs_lock);
-	if(!list_empty(&dv1394_devfs)) {
-		list_for_each(lh, &dv1394_devfs) {
-			p = list_entry(lh, struct dv1394_devfs_entry, list);
-			if(!strncmp(p->name, name, sizeof(p->name))) {
-				goto found;
-			}
-		}
-	}
-	p = NULL;
-	
-found:
-	spin_unlock( &dv1394_devfs_lock);
-	return p;
-}
-
 #ifdef CONFIG_DEVFS_FS
 static int dv1394_devfs_add_entry(struct video_card *video)
 {
-	char buf[32];
-	struct dv1394_devfs_entry *p;
-	struct dv1394_devfs_entry *parent;
+	char buf[64];
 
-	p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL);
-	if(!p) {
-		printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n");
-		goto err;
-	}
-	memset(p, 0, sizeof(struct dv1394_devfs_entry));
-	
-	snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2),
-						(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"));
-		
-	parent = dv1394_devfs_find(buf);
-	if (parent == NULL) {
-		printk(KERN_ERR "dv1394: unable to locate parent devfs of %s\n", buf);
-		goto err_free;
-	}
-	
-	video->devfs_handle = devfs_register(
-						 parent->devfs,
-					     (video->mode == MODE_RECEIVE ? "in" : "out"),
-						 DEVFS_FL_NONE,
-					     IEEE1394_MAJOR,
+	snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/%s/%s",
+		(video->id>>2),
+		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
+		(video->mode == MODE_RECEIVE ? "in" : "out"));
+
+	video->devfs_handle = devfs_register(NULL, buf, 0, IEEE1394_MAJOR,
 					     IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
 					     S_IFCHR | S_IRUGO | S_IWUGO,
-					     &dv1394_fops,
-					     (void*) video);
-	p->devfs = video->devfs_handle;
-
-	if (p->devfs == NULL) {
-		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s/%s\n",
-			parent->name,
-			(video->mode == MODE_RECEIVE ? "in" : "out"));
-		goto err_free;
-	}
-	
-	spin_lock( &dv1394_devfs_lock);
-	INIT_LIST_HEAD(&p->list);
-	list_add_tail(&p->list, &dv1394_devfs);
-	spin_unlock( &dv1394_devfs_lock);
-	
-	return 0;
-	
- err_free:
-	kfree(p);
- err:
-	return -ENOMEM;
-}
-
-static int
-dv1394_devfs_add_dir( char *name,
-					struct dv1394_devfs_entry *parent, 
-					struct dv1394_devfs_entry **out)
-{
-	struct dv1394_devfs_entry *p;
-
-	p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL);
-	if(!p) {
-		printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n");
-		goto err;
-	}
-	memset(p, 0, sizeof(struct dv1394_devfs_entry));
-	
-	if (parent == NULL) {
-		snprintf(p->name, sizeof(p->name), "%s", name);
-		p->devfs = devfs_mk_dir(ieee1394_devfs_handle, name, NULL);
-	} else {
-		snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name);
-		p->devfs = devfs_mk_dir(parent->devfs, name, NULL);
-	}
-	if (p->devfs == NULL) {
-		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s\n", p->name);
-		goto err_free;
+					     &dv1394_fops, video);
+	if (video->devfs_handle == NULL) {
+		printk(KERN_ERR "dv1394: unable to create /dev/%s\n", buf);
+		return -ENOMEM;
 	}
-
-	p->parent = parent;
-	if (out != NULL) *out = p;
-
-	spin_lock( &dv1394_devfs_lock);
-	INIT_LIST_HEAD(&p->list);
-	list_add_tail(&p->list, &dv1394_devfs);
-	spin_unlock( &dv1394_devfs_lock);
-
 	return 0;
-	
- err_free:
-	kfree(p);
- err:
-	return -ENOMEM;
-}
-
-void dv1394_devfs_del( char *name)
-{
-	struct dv1394_devfs_entry *p = dv1394_devfs_find(name);
-	if (p != NULL) {
-		devfs_unregister(p->devfs);
-		
-		spin_lock( &dv1394_devfs_lock);
-		list_del(&p->list);
-		spin_unlock( &dv1394_devfs_lock);
-		kfree(p);
-	}
 }
 #endif /* CONFIG_DEVFS_FS */
 
@@ -2664,7 +2543,7 @@
 	
 #ifdef CONFIG_DEVFS_FS
 	if (dv1394_devfs_add_entry(video) < 0)
-			goto err_free;
+		goto err_free;
 #endif
 
 	debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
@@ -2687,8 +2566,9 @@
 		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
 		(video->mode == MODE_RECEIVE ? "in" : "out")
 		);
+
 #ifdef CONFIG_DEVFS_FS
-	dv1394_devfs_del(buf);
+	devfs_remove("ieee1394/%s", buf);
 #endif
 #ifdef CONFIG_PROC_FS
 	dv1394_procfs_del(buf);
@@ -2726,13 +2606,11 @@
 	spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 
 	n = (video->id >> 2);
+
 #ifdef CONFIG_DEVFS_FS
-	snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n);
-	dv1394_devfs_del(buf);
-	snprintf(buf, sizeof(buf), "dv/host%d/PAL", n);
-	dv1394_devfs_del(buf);
-	snprintf(buf, sizeof(buf), "dv/host%d", n);
-	dv1394_devfs_del(buf);
+	devfs_remove("ieee1394/dv/host%d/NTSC", n);
+	devfs_remove("ieee1394/dv/host%d/PAL", n);
+	devfs_remove("ieee1394/dv/host%d", n);
 #endif
 
 #ifdef CONFIG_PROC_FS
@@ -2770,15 +2648,9 @@
 #endif
 
 #ifdef CONFIG_DEVFS_FS
-{
-	struct dv1394_devfs_entry *devfs_entry = dv1394_devfs_find("dv");
-	if (devfs_entry != NULL) {
-		snprintf(buf, sizeof(buf), "host%d", ohci->id);
-		dv1394_devfs_add_dir(buf, devfs_entry, &devfs_entry);
-		dv1394_devfs_add_dir("NTSC", devfs_entry, NULL);
-		dv1394_devfs_add_dir("PAL", devfs_entry, NULL);
-	}
-}
+	devfs_mk_dir("ieee1394/dv/host%d", ohci->id);
+	devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id);
+	devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id);
 #endif
 	
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
@@ -3028,7 +2900,7 @@
 	hpsb_unregister_highlevel (hl_handle);
 	ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
-	dv1394_devfs_del("dv");
+	devfs_remove("ieee1394/dv");
 #endif
 #ifdef CONFIG_PROC_FS
 	dv1394_procfs_del("dv");
@@ -3047,8 +2919,7 @@
 	}
 
 #ifdef CONFIG_DEVFS_FS
-	ret = dv1394_devfs_add_dir("dv", NULL, NULL);
-	if (ret < 0) {
+	if (!devfs_mk_dir("ieee1394/dv")) {
 		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 		return -ENOMEM;
@@ -3061,7 +2932,7 @@
 		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
-		dv1394_devfs_del("dv");
+		devfs_remove("ieee1394/dv");
 #endif
 		return -ENOMEM;
 	}
@@ -3072,7 +2943,7 @@
 		printk(KERN_ERR "dv1394: hpsb_register_highlevel failed\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
-		dv1394_devfs_del("dv");
+		devfs_remove("ieee1394/dv");
 #endif
 #ifdef CONFIG_PROC_FS
 		dv1394_procfs_del("dv");
diff -urN linux-2.5.65-bk4/drivers/ieee1394/ieee1394_core.c linux-2.5.65-bk5/drivers/ieee1394/ieee1394_core.c
--- linux-2.5.65-bk4/drivers/ieee1394/ieee1394_core.c	Mon Mar 17 13:43:48 2003
+++ linux-2.5.65-bk5/drivers/ieee1394/ieee1394_core.c	Mon Mar 31 12:44:33 2003
@@ -1155,7 +1155,7 @@
 	hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
 					      0, 0, NULL, NULL);
 
-	ieee1394_devfs_handle = devfs_mk_dir(NULL, "ieee1394", NULL);
+	ieee1394_devfs_handle = devfs_mk_dir("ieee1394");
 
 	if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) {
 		HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
diff -urN linux-2.5.65-bk4/drivers/ieee1394/video1394.c linux-2.5.65-bk5/drivers/ieee1394/video1394.c
--- linux-2.5.65-bk4/drivers/ieee1394/video1394.c	Mon Mar 17 13:43:43 2003
+++ linux-2.5.65-bk5/drivers/ieee1394/video1394.c	Mon Mar 31 12:44:33 2003
@@ -1251,7 +1251,7 @@
 {
 	struct video_card *video;
 	unsigned long flags;
-	char name[16];
+	char name[24];
 	int minor;
 
 	video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
@@ -1270,9 +1270,9 @@
 	video->id = ohci->id;
 	video->ohci = ohci;
 
-	sprintf(name, "%d", video->id);
+	sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, video->id);
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + video->id;
-	video->devfs = devfs_register(devfs_handle, name, DEVFS_FL_DEFAULT,
+	video->devfs = devfs_register(NULL, name, DEVFS_FL_DEFAULT,
 				      IEEE1394_MAJOR, minor,
 				      S_IFCHR | S_IRUSR | S_IWUSR,
 				      &video1394_fops, NULL);
@@ -1486,7 +1486,7 @@
 		return -EIO;
         }
 
-	devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL);
+	devfs_handle = devfs_mk_dir(VIDEO1394_DRIVER_NAME);
 
 	hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
 	if (hl_handle == NULL) {
diff -urN linux-2.5.65-bk4/drivers/input/evdev.c linux-2.5.65-bk5/drivers/input/evdev.c
--- linux-2.5.65-bk4/drivers/input/evdev.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/drivers/input/evdev.c	Mon Mar 31 12:44:33 2003
@@ -397,7 +397,7 @@
 	sprintf(evdev->name, "event%d", minor);
 
 	evdev_table[minor] = evdev;
-	evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
+	evdev->devfs = input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE);
 
 	return &evdev->handle;
 }
diff -urN linux-2.5.65-bk4/drivers/input/input.c linux-2.5.65-bk5/drivers/input/input.c
--- linux-2.5.65-bk4/drivers/input/input.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk5/drivers/input/input.c	Mon Mar 31 12:44:33 2003
@@ -546,8 +546,11 @@
 {
 	char devfs_name[16];
 	sprintf(devfs_name, name, minor);
-	return devfs_register(input_devfs_handle, devfs_name, DEVFS_FL_DEFAULT, INPUT_MAJOR, minor + minor_base,
-		S_IFCHR | S_IRUGO | S_IWUSR, &input_fops, NULL);
+
+	return devfs_register(NULL, devfs_name, 0,
+			INPUT_MAJOR, minor + minor_base,
+			S_IFCHR|S_IRUGO|S_IWUSR,
+			&input_fops, NULL);
 }
 
 void input_unregister_minor(devfs_handle_t handle)
@@ -696,7 +699,7 @@
 		return -EBUSY;
 	}
 
-	input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
+	input_devfs_handle = devfs_mk_dir("input");
 
 	return 0;
 }
diff -urN linux-2.5.65-bk4/drivers/input/mousedev.c linux-2.5.65-bk5/drivers/input/mousedev.c
--- linux-2.5.65-bk4/drivers/input/mousedev.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk5/drivers/input/mousedev.c	Mon Mar 31 12:44:33 2003
@@ -425,7 +425,7 @@
 		input_open_device(&mousedev->handle);
 
 	mousedev_table[minor] = mousedev;
-	mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
+	mousedev->devfs = input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE);
 
 	return &mousedev->handle;
 }
@@ -507,7 +507,7 @@
 	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
-	mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
+	mousedev_mix.devfs = input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	if (!(mousedev_mix.misc = !misc_register(&psaux_mouse)))
diff -urN linux-2.5.65-bk4/drivers/input/tsdev.c linux-2.5.65-bk5/drivers/input/tsdev.c
--- linux-2.5.65-bk4/drivers/input/tsdev.c	Mon Mar 17 13:44:46 2003
+++ linux-2.5.65-bk5/drivers/input/tsdev.c	Mon Mar 31 12:44:33 2003
@@ -326,7 +326,7 @@
 
 	tsdev_table[minor] = tsdev;
 	tsdev->devfs =
-	    input_register_minor("ts%d", minor, TSDEV_MINOR_BASE);
+	    input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE);
 
 
 	return &tsdev->handle;
diff -urN linux-2.5.65-bk4/drivers/isdn/i4l/isdn_common.c linux-2.5.65-bk5/drivers/isdn/i4l/isdn_common.c
--- linux-2.5.65-bk4/drivers/isdn/i4l/isdn_common.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk5/drivers/isdn/i4l/isdn_common.c	Mon Mar 31 12:44:33 2003
@@ -2186,7 +2186,7 @@
 	int i;
 #  endif
 
-	devfs_mk_dir (NULL, "isdn", NULL);
+	devfs_mk_dir("isdn");
 #  ifdef CONFIG_ISDN_PPP
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		char buf[16];
diff -urN linux-2.5.65-bk4/drivers/md/dm-ioctl.c linux-2.5.65-bk5/drivers/md/dm-ioctl.c
--- linux-2.5.65-bk4/drivers/md/dm-ioctl.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk5/drivers/md/dm-ioctl.c	Mon Mar 31 12:44:33 2003
@@ -56,7 +56,7 @@
 {
 	init_buckets(_name_buckets);
 	init_buckets(_uuid_buckets);
-	devfs_mk_dir(NULL, DM_DIR, NULL);
+	devfs_mk_dir(DM_DIR);
 	return 0;
 }
 
@@ -1089,8 +1089,6 @@
 	.owner	 = THIS_MODULE,
 };
 
-static devfs_handle_t _ctl_handle;
-
 static struct miscdevice _dm_misc = {
 	.minor = MISC_DYNAMIC_MINOR,
 	.name  = DM_NAME,
@@ -1115,8 +1113,7 @@
 		return r;
 	}
 
-	r = devfs_mk_symlink(NULL, DM_DIR "/control", DEVFS_FL_DEFAULT,
-			"../misc/" DM_NAME, &_ctl_handle, NULL);
+	r = devfs_mk_symlink(DM_DIR "/control", "../misc/" DM_NAME);
 	if (r) {
 		DMERR("devfs_mk_symlink failed for control device");
 		goto failed;
diff -urN linux-2.5.65-bk4/drivers/md/md.c linux-2.5.65-bk5/drivers/md/md.c
--- linux-2.5.65-bk4/drivers/md/md.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/md/md.c	Mon Mar 31 12:44:33 2003
@@ -3597,7 +3597,7 @@
 	if (register_blkdev(MAJOR_NR, "md"))
 		return -1;
 
-	devfs_mk_dir(NULL, "md", NULL);
+	devfs_mk_dir("md");
 	blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
 				md_probe, NULL, NULL);
 	for (minor=0; minor < MAX_MD_DEVS; ++minor) {
diff -urN linux-2.5.65-bk4/drivers/media/dvb/dvb-core/dvbdev.c linux-2.5.65-bk5/drivers/media/dvb/dvb-core/dvbdev.c
--- linux-2.5.65-bk4/drivers/media/dvb/dvb-core/dvbdev.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/media/dvb/dvb-core/dvbdev.c	Mon Mar 31 12:44:33 2003
@@ -111,8 +111,6 @@
 	.owner =	THIS_MODULE,
 	.open =		dvb_device_open,
 };
-#endif /* CONFIG_DVB_DEVFS_ONLY */
-
 
 
 int dvb_generic_open(struct inode *inode, struct file *file)
@@ -271,7 +269,6 @@
 
 int dvb_register_adapter(struct dvb_adapter **padap, char *name)
 {
-	char dirname[16];
 	struct dvb_adapter *adap;
 	int num;
 
@@ -295,8 +292,7 @@
 
 	printk ("DVB: registering new adapter (%s).\n", name);
 	
-	sprintf(dirname, "dvb/adapter%d", num);
-	adap->devfs_handle = devfs_mk_dir(NULL, dirname, NULL);
+	adap->devfs_handle = devfs_mk_dir("dvb/adapter%d", num);
 	adap->num = num;
 
 	list_add_tail (&adap->list_head, &dvb_adapter_list);
@@ -323,7 +319,7 @@
 static
 int __init init_dvbdev(void)
 {
-	dvb_devfs_handle = devfs_mk_dir (NULL, "dvb", NULL);
+	dvb_devfs_handle = devfs_mk_dir ("dvb");
 #ifndef CONFIG_DVB_DEVFS_ONLY
 	if(register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops)) {
 		printk("video_dev: unable to get major %d\n", DVB_MAJOR);
diff -urN linux-2.5.65-bk4/drivers/media/radio/miropcm20-rds.c linux-2.5.65-bk5/drivers/media/radio/miropcm20-rds.c
--- linux-2.5.65-bk4/drivers/media/radio/miropcm20-rds.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk5/drivers/media/radio/miropcm20-rds.c	Mon Mar 31 12:44:33 2003
@@ -125,8 +125,8 @@
 	if (error)
 		return error;
 
-	error = devfs_mk_symlink(NULL, "v4l/rds/radiotext", 0,
-				 "../misc/radiotext", NULL, NULL);
+	error = devfs_mk_symlink("v4l/rds/radiotext",
+				 "../misc/radiotext");
 	if (error)
 		misc_deregister(&rds_miscdev);
 
diff -urN linux-2.5.65-bk4/drivers/mtd/mtdblock.c linux-2.5.65-bk5/drivers/mtd/mtdblock.c
--- linux-2.5.65-bk4/drivers/mtd/mtdblock.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/drivers/mtd/mtdblock.c	Mon Mar 31 12:44:33 2003
@@ -575,7 +575,7 @@
 		return -EAGAIN;
 
 #ifdef CONFIG_DEVFS_FS
-	devfs_mk_dir(NULL, DEVICE_NAME, NULL);
+	devfs_mk_dir(DEVICE_NAME);
 #endif
 	register_mtd_user(&notifier);
 	
diff -urN linux-2.5.65-bk4/drivers/mtd/mtdchar.c linux-2.5.65-bk5/drivers/mtd/mtdchar.c
--- linux-2.5.65-bk4/drivers/mtd/mtdchar.c	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk5/drivers/mtd/mtdchar.c	Mon Mar 31 12:44:33 2003
@@ -497,7 +497,7 @@
 	}
 
 #ifdef CONFIG_DEVFS_FS
-	devfs_mk_dir(NULL, "mtd", NULL);
+	devfs_mk_dir("mtd");
 
 	register_mtd_user(&notifier);
 #endif
diff -urN linux-2.5.65-bk4/drivers/net/wan/cosa.c linux-2.5.65-bk5/drivers/net/wan/cosa.c
--- linux-2.5.65-bk4/drivers/net/wan/cosa.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/drivers/net/wan/cosa.c	Mon Mar 31 12:44:33 2003
@@ -390,7 +390,7 @@
 		unregister_chrdev(cosa_major, "cosa");
 		return -ENODEV;
 	}
-	devfs_mk_dir (NULL, "cosa", NULL);
+	devfs_mk_dir("cosa");
 	for (i=0; i<nr_cards; i++) {
 		char name[16];
 		sprintf(name, "cosa/%d", i);
diff -urN linux-2.5.65-bk4/drivers/net/wireless/airo_cs.c linux-2.5.65-bk5/drivers/net/wireless/airo_cs.c
--- linux-2.5.65-bk4/drivers/net/wireless/airo_cs.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk5/drivers/net/wireless/airo_cs.c	Mon Mar 31 12:44:33 2003
@@ -626,26 +626,25 @@
 	return 0;
 } /* airo_event */
 
-/*====================================================================*/
+static struct pcmcia_driver airo_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "airo_cs",
+	},
+	.attach		= airo_attach,
+	.detach		= airo_detach,
+};
 
 static int airo_cs_init(void)
 {
-	servinfo_t serv;
-	DEBUG(0, "%s\n", version);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "airo_cs: Card Services release "
-		       "does not match!\n");
-		return -1;
-	}
-	register_pcmcia_driver(&dev_info, &airo_attach, &airo_detach);
-	return 0;
+	return pcmcia_register_driver(&airo_driver);
 }
 
 static void airo_cs_cleanup(void)
 {
-	DEBUG(0, "airo_cs: unloading\n");
-	unregister_pcmcia_driver(&dev_info);
+	pcmcia_unregister_driver(&airo_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL) {
 		if (dev_list->state & DEV_CONFIG)
 			airo_release((u_long)dev_list);
diff -urN linux-2.5.65-bk4/drivers/net/wireless/ray_cs.c linux-2.5.65-bk5/drivers/net/wireless/ray_cs.c
--- linux-2.5.65-bk4/drivers/net/wireless/ray_cs.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/drivers/net/wireless/ray_cs.c	Mon Mar 31 12:44:33 2003
@@ -2962,12 +2962,21 @@
 }
 #endif
 
+static struct pcmcia_driver ray_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "ray_cs",
+	},
+	.attach		= ray_attach,
+	.detach		= ray_detach,
+};
+
 static int __init init_ray_cs(void)
 {
     int rc;
     
     DEBUG(1, "%s\n", rcsid);
-    rc = register_pcmcia_driver(&dev_info, &ray_attach, &ray_detach);
+    rc = pcmcia_register_driver(&ray_driver);
     DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc);
 
 #ifdef CONFIG_PROC_FS
@@ -2993,7 +3002,7 @@
     remove_proc_entry("ray_cs", proc_root_driver);
 #endif
 
-    unregister_pcmcia_driver(&dev_info);
+    pcmcia_unregister_driver(&ray_driver);
     while (dev_list != NULL)
         ray_detach(dev_list);
 
diff -urN linux-2.5.65-bk4/drivers/parport/parport_pc.c linux-2.5.65-bk5/drivers/parport/parport_pc.c
--- linux-2.5.65-bk4/drivers/parport/parport_pc.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/parport/parport_pc.c	Mon Mar 31 12:44:33 2003
@@ -147,7 +147,7 @@
 	if (mode >= 2 && !(priv->ctr & 0x20)) {
 		/* This mode resets the FIFO, so we may
 		 * have to wait for it to drain first. */
-		long expire = jiffies + p->physport->cad->timeout;
+		unsigned long expire = jiffies + p->physport->cad->timeout;
 		int counter;
 		switch (mode) {
 		case ECR_PPF: /* Parallel Port FIFO mode */
@@ -596,7 +596,7 @@
 	int ret = 0;
 	const unsigned char *bufp = buf;
 	size_t left = length;
-	long expire = jiffies + port->physport->cad->timeout;
+	unsigned long expire = jiffies + port->physport->cad->timeout;
 	const int fifo = FIFO (port);
 	int poll_for = 8; /* 80 usecs */
 	const struct parport_pc_private *priv = port->physport->private_data;
@@ -724,7 +724,7 @@
 	parport_pc_data_forward (port); /* Must be in PS2 mode */
 
 	while (left) {
-		long expire = jiffies + port->physport->cad->timeout;
+		unsigned long expire = jiffies + port->physport->cad->timeout;
 
 		size_t count = left;
 
@@ -816,7 +816,7 @@
 {
 	size_t written;
 	int r;
-	long int expire;
+	unsigned long expire;
 	const struct parport_pc_private *priv = port->physport->private_data;
 
 	/* Special case: a timeout of zero means we cannot call schedule().
@@ -893,7 +893,7 @@
 {
 	size_t written;
 	int r;
-	long int expire;
+	unsigned long expire;
 	const struct parport_pc_private *priv = port->physport->private_data;
 
 	/* Special case: a timeout of zero means we cannot call schedule().
@@ -1111,7 +1111,7 @@
 	/* Do the transfer. */
 	while (left > fifofull) {
 		int ret;
-		long int expire = jiffies + port->cad->timeout;
+		unsigned long expire = jiffies + port->cad->timeout;
 		unsigned char ecrval = inb (ECONTROL (port));
 
 		if (need_resched() && time_before (jiffies, expire))
diff -urN linux-2.5.65-bk4/drivers/parport/share.c linux-2.5.65-bk5/drivers/parport/share.c
--- linux-2.5.65-bk4/drivers/parport/share.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/parport/share.c	Mon Mar 31 12:44:33 2003
@@ -472,7 +472,7 @@
 	portlist_tail = tmp;
 	if (!portlist)
 		portlist = tmp;
-	spin_unlock(&parportlist_lock);
+	spin_unlock_irq(&parportlist_lock);
 
 	for (device = 0; device < 5; device++)
 		/* assume the worst */
diff -urN linux-2.5.65-bk4/drivers/pci/setup-res.c linux-2.5.65-bk5/drivers/pci/setup-res.c
--- linux-2.5.65-bk4/drivers/pci/setup-res.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/pci/setup-res.c	Mon Mar 31 12:44:33 2003
@@ -60,6 +60,7 @@
 	} else {
 		/* Hmm, non-standard resource. */
 		BUG();
+		return;		/* kill uninitialised var warning */
 	}
 
 	pci_write_config_dword(dev, reg, new);
diff -urN linux-2.5.65-bk4/drivers/pnp/isapnp/core.c linux-2.5.65-bk5/drivers/pnp/isapnp/core.c
--- linux-2.5.65-bk4/drivers/pnp/isapnp/core.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk5/drivers/pnp/isapnp/core.c	Mon Mar 31 12:44:33 2003
@@ -72,8 +72,13 @@
 MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_X86_PC9800
+#define _PIDXR		0x259
+#define _PNPWRP		0xa59
+#else
 #define _PIDXR		0x279
 #define _PNPWRP		0xa79
+#endif
 
 /* short tags */
 #define _STAG_PNPVERNO		0x01
diff -urN linux-2.5.65-bk4/drivers/s390/block/dasd.c linux-2.5.65-bk5/drivers/s390/block/dasd.c
--- linux-2.5.65-bk4/drivers/s390/block/dasd.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk5/drivers/s390/block/dasd.c	Mon Mar 31 12:44:33 2003
@@ -174,11 +174,11 @@
 static inline int
 dasd_state_new_to_known(dasd_device_t *device)
 {
-	char buffer[10];
 	dasd_devmap_t *devmap;
 	umode_t devfs_perm;
 	devfs_handle_t dir;
 	int major, minor;
+	char buf[20];
 
 	/* Increase reference count of bdev. */
 	if (bdget(MKDEV(device->gdp->major, device->gdp->first_minor)) == NULL)
@@ -193,14 +193,15 @@
 	minor = devmap->devindex % DASD_PER_MAJOR;
 
 	/* Add a proc directory and the dasd device entry to devfs. */
- 	sprintf(buffer, "dasd/%04x", device->devno);
- 	dir = devfs_mk_dir(NULL, buffer, NULL);
+ 	dir = devfs_mk_dir("dasd/%04x", device->devno);
 	device->gdp->de = dir;
 	if (device->ro_flag)
 		devfs_perm = S_IFBLK | S_IRUSR;
 	else
 		devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR;
-	device->devfs_entry = devfs_register(dir, "device", DEVFS_FL_DEFAULT,
+
+	snprintf(buf, sizeof(buf), "dasd/%04x/device", device->devno);
+	device->devfs_entry = devfs_register(NULL, buf, 0,
 					     major, minor << DASD_PARTN_BITS,
 					     devfs_perm,
 					     &dasd_device_operations, NULL);
@@ -2077,7 +2078,7 @@
 
 	DBF_EVENT(DBF_EMERG, "%s", "debug area created");
 
-	if (devfs_mk_dir(NULL, "dasd", NULL)) {
+	if (devfs_mk_dir("dasd")) {
 		DBF_EVENT(DBF_ALERT, "%s", "no devfs");
 		rc = -ENOSYS;
 		goto failed;
diff -urN linux-2.5.65-bk4/drivers/s390/block/xpram.c linux-2.5.65-bk5/drivers/s390/block/xpram.c
--- linux-2.5.65-bk4/drivers/s390/block/xpram.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk5/drivers/s390/block/xpram.c	Mon Mar 31 12:44:33 2003
@@ -434,7 +434,7 @@
 	if (rc < 0)
 		goto out;
 
-	devfs_mk_dir(NULL, "slram", NULL);
+	devfs_mk_dir("slram");
 
 	/*
 	 * Assign the other needed values: make request function, sizes and
diff -urN linux-2.5.65-bk4/drivers/s390/char/tubfs.c linux-2.5.65-bk5/drivers/s390/char/tubfs.c
--- linux-2.5.65-bk4/drivers/s390/char/tubfs.c	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk5/drivers/s390/char/tubfs.c	Mon Mar 31 12:44:33 2003
@@ -73,9 +73,8 @@
 		return -1;
 	}
 #ifdef CONFIG_DEVFS_FS
-	fs3270_devfs_dir = devfs_mk_dir(NULL, "3270", NULL);
-	fs3270_devfs_tub = 
-		devfs_register(fs3270_devfs_dir, "tub", DEVFS_FL_DEFAULT,
+	fs3270_devfs_dir = devfs_mk_dir("3270");
+	fs3270_devfs_tub = devfs_register(NULL, "3270/tub", 0,
 			       IBM_FS3270_MAJOR, 0,
 			       S_IFCHR | S_IRUGO | S_IWUGO, 
 			       &fs3270_fops, NULL);
diff -urN linux-2.5.65-bk4/drivers/sbus/char/bpp.c linux-2.5.65-bk5/drivers/sbus/char/bpp.c
--- linux-2.5.65-bk4/drivers/sbus/char/bpp.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/drivers/sbus/char/bpp.c	Mon Mar 31 12:44:33 2003
@@ -1049,7 +1049,7 @@
 		instances[idx].opened = 0;
 		probeLptPort(idx);
 	}
-	devfs_mk_dir (NULL, "bpp", NULL);
+	devfs_mk_dir("bpp");
 	for (idx = 0; idx < BPP_NO; idx++) {
 		char name[16];
 		sprintf(name, "bpp/%d", idx);
diff -urN linux-2.5.65-bk4/drivers/sbus/char/vfc_dev.c linux-2.5.65-bk5/drivers/sbus/char/vfc_dev.c
--- linux-2.5.65-bk4/drivers/sbus/char/vfc_dev.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk5/drivers/sbus/char/vfc_dev.c	Mon Mar 31 12:44:33 2003
@@ -681,7 +681,7 @@
 		kfree(vfc_dev_lst);
 		return -EIO;
 	}
-	devfs_mk_dir (NULL, "vfc", NULL);
+	devfs_mk_dir("vfc");
 	instance = 0;
 	for_all_sbusdev(sdev, sbus) {
 		if (strcmp(sdev->prom_name, "vfc") == 0) {
diff -urN linux-2.5.65-bk4/drivers/scsi/3w-xxxx.c linux-2.5.65-bk5/drivers/scsi/3w-xxxx.c
--- linux-2.5.65-bk4/drivers/scsi/3w-xxxx.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/scsi/3w-xxxx.c	Mon Mar 31 12:44:33 2003
@@ -622,7 +622,7 @@
 	int error, request_id;
 	dma_addr_t dma_handle;
 	unsigned short tw_aen_code;
-	unsigned long before, timeout;
+	unsigned long before;
 	unsigned long flags;
 	unsigned int data_buffer_length = 0;
 	unsigned long data_buffer_length_adjusted = 0;
@@ -635,7 +635,8 @@
 	dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
 
 	/* Only let one of these through at a time */
-	down(&tw_dev->ioctl_sem);
+	if (down_interruptible(&tw_dev->ioctl_sem))
+		return -EINTR;
 
 	/* First copy down the buffer length */
 	error = copy_from_user(&data_buffer_length, (void *)arg, sizeof(unsigned int));
@@ -654,7 +655,7 @@
 	/* Now allocate ioctl buf memory */
 	cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle);
 	if (cpu_addr == NULL) {
-		retval -ENOMEM;
+		retval = -ENOMEM;
 		goto out;
 	}
 
diff -urN linux-2.5.65-bk4/drivers/scsi/pcmcia/nsp_cs.c linux-2.5.65-bk5/drivers/scsi/pcmcia/nsp_cs.c
--- linux-2.5.65-bk4/drivers/scsi/pcmcia/nsp_cs.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk5/drivers/scsi/pcmcia/nsp_cs.c	Mon Mar 31 12:44:33 2003
@@ -1987,32 +1987,26 @@
 	return 0;
 } /* nsp_cs_event */
 
-/*======================================================================*
- *	module entry point
- *====================================================================*/
+static struct pcmcia_driver nsp_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "nsp_cs",
+	},
+	.attach		= nsp_cs_attach,
+	.detach		= nsp_cs_detach,
+};
+
 static int __init nsp_cs_init(void)
 {
-	servinfo_t serv;
-
-	DEBUG(0, "%s: in\n", __FUNCTION__);
-	DEBUG(0, "%s\n", version);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_DEBUG "nsp_cs: Card Services release "
-		       "does not match!\n");
-		return -1;
-	}
-	register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);
-
-	DEBUG(0, "%s: out\n", __FUNCTION__);
-	return 0;
+	return pcmcia_register_driver(&nsp_driver);
 }
 
 
-static void __exit nsp_cs_cleanup(void)
+static void __exit nsp_cs_exit(void)
 {
-	DEBUG(0, "%s: unloading\n", __FUNCTION__);
-	unregister_pcmcia_driver(&dev_info);
+	pcmcia_unregister_driver(&nsp_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL) {
 		if (dev_list->state & DEV_CONFIG) {
 			nsp_cs_release((u_long)dev_list);
@@ -2022,11 +2016,4 @@
 }
 
 module_init(nsp_cs_init)
-module_exit(nsp_cs_cleanup)
-
-/*
- *
- *
- */
-
-/* end */
+module_exit(nsp_cs_exit)
diff -urN linux-2.5.65-bk4/drivers/scsi/scsi.c linux-2.5.65-bk5/drivers/scsi/scsi.c
--- linux-2.5.65-bk4/drivers/scsi/scsi.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk5/drivers/scsi/scsi.c	Mon Mar 31 12:44:33 2003
@@ -1495,7 +1495,7 @@
 		INIT_LIST_HEAD(&done_q[i]);
 
 	scsi_host_init();
-	devfs_mk_dir(NULL, "scsi", NULL);
+	devfs_mk_dir("scsi");
 	open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
 	printk(KERN_NOTICE "SCSI subsystem initialized\n");
 	return 0;
diff -urN linux-2.5.65-bk4/drivers/scsi/scsi_scan.c linux-2.5.65-bk5/drivers/scsi/scsi_scan.c
--- linux-2.5.65-bk4/drivers/scsi/scsi_scan.c	Mon Mar 17 13:44:39 2003
+++ linux-2.5.65-bk5/drivers/scsi/scsi_scan.c	Mon Mar 31 12:44:33 2003
@@ -1128,8 +1128,6 @@
 static int scsi_add_lun(Scsi_Device *sdev, Scsi_Request *sreq,
 		char *inq_result, int *bflags)
 {
-	char devname[64];
-
 	/*
 	 * XXX do not save the inquiry, since it can change underneath us,
 	 * save just vendor/model/rev.
@@ -1230,13 +1228,10 @@
 	
 	scsi_device_register(sdev);
 
-	sprintf(devname, "scsi/host%d/bus%d/target%d/lun%d",
-		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
-	if (sdev->de)
-		printk(KERN_WARNING "scsi devfs dir: \"%s\" already exists\n",
-		       devname);
-	else
-		sdev->de = devfs_mk_dir(NULL, devname, NULL);
+	sdev->de = devfs_mk_dir("scsi/host%d/bus%d/target%d/lun%d",
+				sdev->host->host_no, sdev->channel,
+				sdev->id, sdev->lun);
+
 	/*
 	 * End driverfs/devfs code.
 	 */
diff -urN linux-2.5.65-bk4/drivers/telephony/ixj_pcmcia.c linux-2.5.65-bk5/drivers/telephony/ixj_pcmcia.c
--- linux-2.5.65-bk4/drivers/telephony/ixj_pcmcia.c	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk5/drivers/telephony/ixj_pcmcia.c	Mon Mar 31 12:44:33 2003
@@ -310,29 +310,30 @@
 	return 0;
 }
 
-int __init ixj_register_pcmcia(void)
+static struct pcmcia_driver ixj_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "ixj_cs",
+	},
+	.attach		= ixj_attach,
+	.detach		= ixj_detach,
+};
+
+static int __init ixj_pcmcia_init(void)
 {
-	servinfo_t serv;
-	DEBUG(0, "%s\n", version);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "ixj_cs: Card Services release does not match!\n");
-		return -EINVAL;
-	}
-	register_pcmcia_driver(&dev_info, &ixj_attach, &ixj_detach);
-	return 0;
+	return pcmcia_register_driver(&ixj_driver);
 }
 
-static void ixj_pcmcia_unload(void)
+static void ixj_pcmcia_exit(void)
 {
-	DEBUG(0, "ixj_cs: unloading\n");
-	unregister_pcmcia_driver(&dev_info);
+	pcmcia_unregister_driver(&ixj_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL)
 		ixj_detach(dev_list);
 }
 
-module_init(ixj_register_pcmcia);
-module_exit(ixj_pcmcia_unload);
+module_init(ixj_pcmcia_init);
+module_exit(ixj_pcmcia_exit);
 
 MODULE_LICENSE("GPL");
-
diff -urN linux-2.5.65-bk4/drivers/usb/core/file.c linux-2.5.65-bk5/drivers/usb/core/file.c
--- linux-2.5.65-bk4/drivers/usb/core/file.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk5/drivers/usb/core/file.c	Mon Mar 31 12:44:33 2003
@@ -76,7 +76,7 @@
 		return -EBUSY;
 	}
 
-	usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
+	usb_devfs_handle = devfs_mk_dir("usb");
 
 	return 0;
 }
diff -urN linux-2.5.65-bk4/drivers/usb/input/hiddev.c linux-2.5.65-bk5/drivers/usb/input/hiddev.c
--- linux-2.5.65-bk4/drivers/usb/input/hiddev.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk5/drivers/usb/input/hiddev.c	Mon Mar 31 12:44:33 2003
@@ -684,7 +684,7 @@
 	struct hiddev *hiddev;
 	int minor, i;
 	int retval;
-	char devfs_name[16];
+	char devfs_name[24];
 
 	for (i = 0; i < hid->maxcollection; i++)
 		if (hid->collection[i].type == 
@@ -715,8 +715,8 @@
 	hiddev->hid = hid;
 	hiddev->exist = 1;
 
-	sprintf(devfs_name, "hiddev%d", minor);
-	hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
+	sprintf(devfs_name, "usb/hid/hiddev%d", minor);
+	hiddev->devfs = devfs_register(NULL, devfs_name,
 		DEVFS_FL_DEFAULT, USB_MAJOR, minor + HIDDEV_MINOR_BASE,
 		S_IFCHR | S_IRUGO | S_IWUSR, &hiddev_fops, NULL);
 	hid->minor = minor;
@@ -774,7 +774,7 @@
 
 int __init hiddev_init(void)
 {
-	hiddev_devfs_handle = devfs_mk_dir(NULL, "usb/hid", NULL);
+	hiddev_devfs_handle = devfs_mk_dir("usb/hid");
 	usb_register(&hiddev_driver);
 	return 0;
 }
diff -urN linux-2.5.65-bk4/drivers/usb/misc/tiglusb.c linux-2.5.65-bk5/drivers/usb/misc/tiglusb.c
--- linux-2.5.65-bk4/drivers/usb/misc/tiglusb.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/drivers/usb/misc/tiglusb.c	Mon Mar 31 12:44:33 2003
@@ -478,7 +478,7 @@
 	}
 
 	/* Use devfs, tree: /dev/ticables/usb/[0..3] */
-	devfs_mk_dir (NULL, "ticables/usb", NULL);
+	devfs_mk_dir ("ticables/usb");
 
 	/* register USB module */
 	result = usb_register (&tiglusb_driver);
diff -urN linux-2.5.65-bk4/drivers/video/fbmem.c linux-2.5.65-bk5/drivers/video/fbmem.c
--- linux-2.5.65-bk4/drivers/video/fbmem.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/drivers/video/fbmem.c	Mon Mar 31 12:44:34 2003
@@ -1274,7 +1274,7 @@
 
 	create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
 
-	devfs_mk_dir(NULL, "fb", NULL);
+	devfs_mk_dir("fb");
 	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
 		printk("unable to get major %d for fb devs\n", FB_MAJOR);
 
diff -urN linux-2.5.65-bk4/fs/bio.c linux-2.5.65-bk5/fs/bio.c
--- linux-2.5.65-bk4/fs/bio.c	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk5/fs/bio.c	Mon Mar 31 12:44:34 2003
@@ -7,7 +7,6 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
@@ -17,6 +16,7 @@
  *
  */
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/bio.h>
 #include <linux/blk.h>
 #include <linux/slab.h>
diff -urN linux-2.5.65-bk4/fs/compat.c linux-2.5.65-bk5/fs/compat.c
--- linux-2.5.65-bk4/fs/compat.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk5/fs/compat.c	Mon Mar 31 12:44:34 2003
@@ -191,7 +191,7 @@
 	case F_GETLK:
 	case F_SETLK:
 	case F_SETLKW:
-		ret = get_compat_flock(&f, (struct compat_flock *)arg);
+		ret = get_compat_flock(&f, compat_ptr(arg));
 		if (ret != 0)
 			break;
 		old_fs = get_fs();
@@ -203,15 +203,14 @@
 			    ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
 				ret = -EOVERFLOW;
 			if (ret == 0)
-				ret = put_compat_flock(&f,
-						(struct compat_flock *)arg);
+				ret = put_compat_flock(&f, compat_ptr(arg));
 		}
 		break;
 
 	case F_GETLK64:
 	case F_SETLK64:
 	case F_SETLKW64:
-		ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+		ret = get_compat_flock64(&f, compat_ptr(arg));
 		if (ret != 0)
 			break;
 		old_fs = get_fs();
@@ -226,8 +225,7 @@
 			    ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
 				ret = -EOVERFLOW;
 			if (ret == 0)
-				ret = put_compat_flock64(&f,
-						(struct compat_flock64 *)arg);
+				ret = put_compat_flock64(&f, compat_ptr(arg));
 		}
 		break;
 
diff -urN linux-2.5.65-bk4/fs/devfs/base.c linux-2.5.65-bk5/fs/devfs/base.c
--- linux-2.5.65-bk4/fs/devfs/base.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/fs/devfs/base.c	Mon Mar 31 12:44:34 2003
@@ -1607,8 +1607,7 @@
 }   /*  End Function devfs_unregister  */
 
 static int devfs_do_symlink (devfs_handle_t dir, const char *name,
-			     unsigned int flags, const char *link,
-			     devfs_handle_t *handle, void *info)
+			     const char *link, devfs_handle_t *handle)
 {
     int err;
     unsigned int linklength;
@@ -1638,7 +1637,7 @@
 	kfree (newlink);
 	return -ENOTDIR;
     }
-    de->info = info;
+    de->info = NULL;
     de->u.symlink.linkname = newlink;
     de->u.symlink.length = linklength;
     if ( ( err = _devfs_append_entry (dir, de, NULL) ) != 0 )
@@ -1660,40 +1659,31 @@
 
 /**
  *	devfs_mk_symlink Create a symbolic link in the devfs namespace.
- *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
- *		new name is relative to the root of the devfs.
- *	@name: The name of the entry.
- *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*).
- *	@link: The destination name.
- *	@handle: The handle to the symlink entry is written here. This may be %NULL.
- *	@info: An arbitrary pointer which will be associated with the entry.
+ *	@from: The name of the entry.
+ *	@to: Name of the destination
  *
  *	Returns 0 on success, else a negative error code is returned.
  */
 
-int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags,
-		      const char *link, devfs_handle_t *handle, void *info)
+int devfs_mk_symlink(const char *from, const char *to)
 {
-    int err;
-    devfs_handle_t de;
+	devfs_handle_t de;
+	int err;
 
-    if (handle != NULL) *handle = NULL;
-    DPRINTK (DEBUG_REGISTER, "(%s)\n", name);
-    err = devfs_do_symlink (dir, name, flags, link, &de, info);
-    if (err) return err;
-    if (handle == NULL) de->vfs_deletable = TRUE;
-    else *handle = de;
-    devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT);
-    return 0;
-}   /*  End Function devfs_mk_symlink  */
+	err = devfs_do_symlink(NULL, from, to, &de);
+	if (!err) {
+		de->vfs_deletable = TRUE;
+		devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED, 0);
+	}
+
+	return err;
+}
 
 
 /**
  *	devfs_mk_dir - Create a directory in the devfs namespace.
- *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
  *		new name is relative to the root of the devfs.
- *	@name: The name of the entry.
- *	@info: An arbitrary pointer which will be associated with the entry.
+ *	@fmt: The name of the entry.
  *
  *	Use of this function is optional. The devfs_register() function
  *	will automatically create intermediate directories as needed. This function
@@ -1702,36 +1692,42 @@
  *	On failure %NULL is returned.
  */
 
-devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info)
+devfs_handle_t devfs_mk_dir(const char *fmt, ...)
 {
-    int err;
-    struct devfs_entry *de, *old;
+	struct devfs_entry *dir = NULL, *de = NULL, *old;
+	char buf[64];
+	va_list args;
+	int n;
 
-    if (name == NULL)
-    {
-	PRINTK ("(): NULL name pointer\n");
-	return NULL;
-    }
-    if ( ( de = _devfs_prepare_leaf (&dir, name, MODE_DIR) ) == NULL )
-    {
-	PRINTK ("(%s): could not prepare leaf\n", name);
-	return NULL;
-    }
-    de->info = info;
-    if ( ( err = _devfs_append_entry (dir, de, &old) ) != 0 )
-    {
-	PRINTK ("(%s): could not append to dir: %p \"%s\", err: %d\n",
-		name, dir, dir->name, err);
-	devfs_put (old);
-	devfs_put (dir);
-	return NULL;
-    }
-    DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\"\n",
-	     name, de, dir, dir->name);
-    devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, 0);
-    devfs_put (dir);
-    return de;
-}   /*  End Function devfs_mk_dir  */
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	if (n >= 64 || !buf[0]) {
+		printk(KERN_WARNING "%s: invalid argument.", __FUNCTION__);
+		return NULL;
+	}
+
+	de = _devfs_prepare_leaf(&dir, buf, MODE_DIR);
+	if (!de) {
+		PRINTK("(%s): could not prepare leaf\n", buf);
+		return NULL;
+	}
+
+	de->info = NULL;
+	if (_devfs_append_entry(dir, de, &old)) {
+		PRINTK("(%s): could not append to dir: %p \"%s\"\n",
+				buf, dir, dir->name);
+		devfs_put(old);
+		goto out_put;
+	}
+	
+	DPRINTK(DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\"\n",
+			buf, de, dir, dir->name);
+	devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED, 0);
+
+ out_put:
+	devfs_put(dir);
+	return de;
+}
 
 
 void devfs_remove(const char *fmt, ...)
@@ -2397,8 +2393,7 @@
     /*  First try to get the devfs entry for this directory  */
     parent = get_devfs_entry_from_vfs_inode (dir);
     if (parent == NULL) return -ENOENT;
-    err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
-			    symname, &de, NULL);
+    err = devfs_do_symlink (parent, dentry->d_name.name, symname, &de);
     DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
 	     dentry->d_name.name, err);
     if (err < 0) return err;
diff -urN linux-2.5.65-bk4/fs/devfs/util.c linux-2.5.65-bk5/fs/devfs/util.c
--- linux-2.5.65-bk4/fs/devfs/util.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk5/fs/devfs/util.c	Mon Mar 31 12:44:34 2003
@@ -87,7 +87,6 @@
 int devfs_register_tape (devfs_handle_t de)
 {
     int pos;
-    devfs_handle_t slave;
     char name[32], dest[64];
     static unsigned int tape_counter;
     int n = tape_counter++;
@@ -96,7 +95,7 @@
     if (pos < 0) return -1;
     strncpy (dest + pos, "../", 3);
     sprintf (name, "tapes/tape%u", n);
-    devfs_mk_symlink (NULL, name, DEVFS_FL_DEFAULT, dest + pos, &slave, NULL);
+    devfs_mk_symlink (name, dest + pos);
     return n;
 }   /*  End Function devfs_register_tape  */
 EXPORT_SYMBOL(devfs_register_tape);
diff -urN linux-2.5.65-bk4/fs/partitions/check.c linux-2.5.65-bk5/fs/partitions/check.c
--- linux-2.5.65-bk4/fs/partitions/check.c	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/fs/partitions/check.c	Mon Mar 31 12:44:34 2003
@@ -185,7 +185,7 @@
 {
 #ifdef CONFIG_DEVFS_FS
 	int pos = 0;
-	devfs_handle_t dir, slave;
+	devfs_handle_t dir;
 	char dirname[64], symlink[16];
 
 	if (dev->flags & GENHD_FL_DEVFS) {
@@ -200,13 +200,12 @@
 		/*  Unaware driver: construct "real" directory  */
 		sprintf(dirname, "../%s/disc%d", dev->disk_name,
 			dev->first_minor >> dev->minor_shift);
-		dir = devfs_mk_dir(NULL, dirname + 3, NULL);
+		dir = devfs_mk_dir(dirname + 3);
 		dev->de = dir;
 	}
 	dev->number = devfs_alloc_unique_number (&disc_numspace);
 	sprintf(symlink, "discs/disc%d", dev->number);
-	devfs_mk_symlink(NULL, symlink, DEVFS_FL_DEFAULT,
-			  dirname + pos, &slave, NULL);
+	devfs_mk_symlink(symlink, dirname + pos);
 	dev->disk_de = devfs_register(dir, "disc", 0,
 			    dev->major, dev->first_minor,
 			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
@@ -222,7 +221,6 @@
 	sprintf(vname, "cdroms/cdrom%d", dev->number);
 	if (dev->de) {
 		int pos;
-		devfs_handle_t slave;
 		char rname[64];
 
 		dev->disk_de = devfs_register(dev->de, "cd", DEVFS_FL_DEFAULT,
@@ -233,8 +231,7 @@
 		pos = devfs_generate_path(dev->disk_de, rname+3, sizeof(rname)-3);
 		if (pos >= 0) {
 			strncpy(rname + pos, "../", 3);
-			devfs_mk_symlink(NULL, vname, DEVFS_FL_DEFAULT,
-					 rname + pos, &slave, NULL);
+			devfs_mk_symlink(vname, rname + pos);
 		}
 	} else {
 		dev->disk_de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT,
diff -urN linux-2.5.65-bk4/include/asm-generic/tlb.h linux-2.5.65-bk5/include/asm-generic/tlb.h
--- linux-2.5.65-bk4/include/asm-generic/tlb.h	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk5/include/asm-generic/tlb.h	Mon Mar 31 12:44:34 2003
@@ -14,6 +14,7 @@
 #define _ASM_GENERIC__TLB_H
 
 #include <linux/config.h>
+#include <linux/swap.h>
 #include <asm/tlbflush.h>
 
 /*
diff -urN linux-2.5.65-bk4/include/asm-i386/hardirq.h linux-2.5.65-bk5/include/asm-i386/hardirq.h
--- linux-2.5.65-bk4/include/asm-i386/hardirq.h	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk5/include/asm-i386/hardirq.h	Mon Mar 31 12:44:34 2003
@@ -79,7 +79,7 @@
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-#if CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT
 # define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
diff -urN linux-2.5.65-bk4/include/asm-parisc/compat.h linux-2.5.65-bk5/include/asm-parisc/compat.h
--- linux-2.5.65-bk4/include/asm-parisc/compat.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/asm-parisc/compat.h	Mon Mar 31 12:44:34 2003
@@ -104,4 +104,17 @@
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef	u32		compat_uptr_t;
+
+static inline void *compat_ptr(compat_uptr_t uptr)
+{
+	return (void *)uptr;
+}
+
 #endif /* _ASM_PARISC_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/asm-ppc64/compat.h linux-2.5.65-bk5/include/asm-ppc64/compat.h
--- linux-2.5.65-bk4/include/asm-ppc64/compat.h	Mon Mar 17 13:43:48 2003
+++ linux-2.5.65-bk5/include/asm-ppc64/compat.h	Mon Mar 31 12:44:34 2003
@@ -98,4 +98,17 @@
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef	u32		compat_uptr_t;
+
+static inline void *compat_ptr(compat_uptr_t uptr)
+{
+	return (void *)uptr;
+}
+
 #endif /* _ASM_PPC64_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/asm-s390x/compat.h linux-2.5.65-bk5/include/asm-s390x/compat.h
--- linux-2.5.65-bk4/include/asm-s390x/compat.h	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk5/include/asm-s390x/compat.h	Mon Mar 31 12:44:34 2003
@@ -101,4 +101,17 @@
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef	u32		compat_uptr_t;
+
+static inline void *compat_ptr(compat_uptr_t uptr)
+{
+	return (void *)(uptr & 0x7fffffffUL);
+}
+
 #endif /* _ASM_S390X_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/asm-sparc64/compat.h linux-2.5.65-bk5/include/asm-sparc64/compat.h
--- linux-2.5.65-bk4/include/asm-sparc64/compat.h	Mon Mar 17 13:44:14 2003
+++ linux-2.5.65-bk5/include/asm-sparc64/compat.h	Mon Mar 31 12:44:34 2003
@@ -100,4 +100,17 @@
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef	u32		compat_uptr_t;
+
+static inline void *compat_ptr(compat_uptr_t uptr)
+{
+	return (void *)(unsigned long)uptr;
+}
+
 #endif /* _ASM_SPARC64_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/asm-sparc64/ide.h linux-2.5.65-bk5/include/asm-sparc64/ide.h
--- linux-2.5.65-bk4/include/asm-sparc64/ide.h	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/include/asm-sparc64/ide.h	Mon Mar 31 12:44:34 2003
@@ -17,8 +17,13 @@
 #include <asm/page.h>
 #include <asm/spitfire.h>
 
-#undef  MAX_HWIFS
+#ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
+#define MAX_HWIFS	10
+# else
 #define MAX_HWIFS	2
+# endif
+#endif
 
 static __inline__ int ide_default_irq(unsigned long base)
 {
diff -urN linux-2.5.65-bk4/include/asm-sparc64/pgtable.h linux-2.5.65-bk5/include/asm-sparc64/pgtable.h
--- linux-2.5.65-bk4/include/asm-sparc64/pgtable.h	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/include/asm-sparc64/pgtable.h	Mon Mar 31 12:44:34 2003
@@ -123,6 +123,7 @@
 #define _PAGE_G		0x0000000000000001	/* Global                             */
 
 /* Here are the SpitFire software bits we use in the TTE's. */
+#define _PAGE_FILE	0x0000000000001000	/* Pagecache page                     */
 #define _PAGE_MODIFIED	0x0000000000000800	/* Modified Page (ie. dirty)          */
 #define _PAGE_ACCESSED	0x0000000000000400	/* Accessed Page (ie. referenced)     */
 #define _PAGE_READ	0x0000000000000200	/* Readable SW Bit                    */
@@ -311,6 +312,12 @@
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
 
+/* File offset in PTE support. */
+#define pte_file(pte)		(pte_val(pte) & _PAGE_FILE)
+#define pte_to_pgoff(pte)	(pte_val(pte) >> PAGE_SHIFT)
+#define pgoff_to_pte(off)	(__pte(((off) << PAGE_SHIFT) | _PAGE_FILE))
+#define PTE_FILE_MAX_BITS	(64UL - PAGE_SHIFT - 1UL)
+
 extern unsigned long prom_virt_to_phys(unsigned long, int *);
 
 static __inline__ unsigned long
diff -urN linux-2.5.65-bk4/include/asm-x86_64/compat.h linux-2.5.65-bk5/include/asm-x86_64/compat.h
--- linux-2.5.65-bk4/include/asm-x86_64/compat.h	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/include/asm-x86_64/compat.h	Mon Mar 31 12:44:34 2003
@@ -107,4 +107,17 @@
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffff
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef	u32		compat_uptr_t;
+
+static inline void *compat_ptr(compat_uptr_t uptr)
+{
+	return (void *)uptr;
+}
+
 #endif /* _ASM_X86_64_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/linux/compat.h linux-2.5.65-bk5/include/linux/compat.h
--- linux-2.5.65-bk4/include/linux/compat.h	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk5/include/linux/compat.h	Mon Mar 31 12:44:34 2003
@@ -43,11 +43,9 @@
 extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
 
 struct compat_iovec {
-	u32		iov_base;
+	compat_uptr_t	iov_base;
 	compat_size_t	iov_len;
 };
-#else /* no CONFIG_COMPAT */
-#define compat_size_t	size_t
 
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/linux/devfs_fs_kernel.h linux-2.5.65-bk5/include/linux/devfs_fs_kernel.h
--- linux-2.5.65-bk4/include/linux/devfs_fs_kernel.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/linux/devfs_fs_kernel.h	Mon Mar 31 12:44:34 2003
@@ -22,8 +22,6 @@
 
 #ifdef CONFIG_DEVFS_FS
 
-extern void devfs_remove(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-
 struct unique_numspace
 {
     spinlock_t init_lock;
@@ -41,11 +39,11 @@
 				      unsigned int major, unsigned int minor,
 				      umode_t mode, void *ops, void *info);
 extern void devfs_unregister (devfs_handle_t de);
-extern int devfs_mk_symlink (devfs_handle_t dir, const char *name,
-			     unsigned int flags, const char *link,
-			     devfs_handle_t *handle, void *info);
-extern devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name,
-				    void *info);
+extern int devfs_mk_symlink (const char *name, const char *link);
+extern devfs_handle_t devfs_mk_dir(const char *fmt, ...)
+	__attribute__((format (printf, 1, 2)));
+extern void devfs_remove(const char *fmt, ...)
+	__attribute__((format (printf, 1, 2)));
 extern int devfs_generate_path (devfs_handle_t de, char *path, int buflen);
 extern int devfs_register_tape (devfs_handle_t de);
 extern void devfs_unregister_tape(int num);
@@ -78,14 +76,11 @@
 {
     return;
 }
-static inline int devfs_mk_symlink (devfs_handle_t dir, const char *name,
-				    unsigned int flags, const char *link,
-				    devfs_handle_t *handle, void *info)
+static inline int devfs_mk_symlink (const char *name, const char *link)
 {
     return 0;
 }
-static inline devfs_handle_t devfs_mk_dir (devfs_handle_t dir,
-					   const char *name, void *info)
+static inline devfs_handle_t devfs_mk_dir(const char *fmt, ...)
 {
     return NULL;
 }
diff -urN linux-2.5.65-bk4/include/linux/in6.h linux-2.5.65-bk5/include/linux/in6.h
--- linux-2.5.65-bk4/include/linux/in6.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/linux/in6.h	Mon Mar 31 12:44:34 2003
@@ -180,5 +180,8 @@
 #define IPV6_FLOWLABEL_MGR	32
 #define IPV6_FLOWINFO_SEND	33
 
+#define IPV6_IPSEC_POLICY	34
+#define IPV6_XFRM_POLICY	35
+
 
 #endif
diff -urN linux-2.5.65-bk4/include/linux/mm.h linux-2.5.65-bk5/include/linux/mm.h
--- linux-2.5.65-bk4/include/linux/mm.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/linux/mm.h	Mon Mar 31 12:44:34 2003
@@ -8,10 +8,8 @@
 
 #include <linux/config.h>
 #include <linux/gfp.h>
-#include <linux/string.h>
 #include <linux/list.h>
 #include <linux/mmzone.h>
-#include <linux/swap.h>
 #include <linux/rbtree.h>
 #include <linux/fs.h>
 
@@ -142,6 +140,7 @@
 /* forward declaration; pte_chain is meant to be internal to rmap.c */
 struct pte_chain;
 struct mmu_gather;
+struct inode;
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -490,10 +489,7 @@
 extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
-#ifdef CONFIG_NUMA
 extern void si_meminfo_node(struct sysinfo *val, int nid);
-#endif
-extern void swapin_readahead(swp_entry_t);
 
 /* mmap.c */
 extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
diff -urN linux-2.5.65-bk4/include/linux/netfilter_bridge/ebtables.h linux-2.5.65-bk5/include/linux/netfilter_bridge/ebtables.h
--- linux-2.5.65-bk4/include/linux/netfilter_bridge/ebtables.h	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk5/include/linux/netfilter_bridge/ebtables.h	Mon Mar 31 12:44:34 2003
@@ -260,6 +260,7 @@
 	   unsigned int valid_hooks);
 	/* the data used by the kernel */
 	struct ebt_table_info *private;
+	struct module *me;
 };
 
 extern int ebt_register_table(struct ebt_table *table);
diff -urN linux-2.5.65-bk4/include/linux/nfsd/syscall.h linux-2.5.65-bk5/include/linux/nfsd/syscall.h
--- linux-2.5.65-bk4/include/linux/nfsd/syscall.h	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk5/include/linux/nfsd/syscall.h	Mon Mar 31 12:44:34 2003
@@ -34,8 +34,8 @@
 #define NFSCTL_DELCLIENT	2	/* Remove an NFS client. */
 #define NFSCTL_EXPORT		3	/* export a file system. */
 #define NFSCTL_UNEXPORT		4	/* unexport a file system. */
-#define NFSCTL_UGIDUPDATE	5	/* update a client's uid/gid map. */
-#define NFSCTL_GETFH		6	/* get an fh by ino (used by mountd) */
+/*#define NFSCTL_UGIDUPDATE	5	/ * update a client's uid/gid map. DISCARDED */
+/*#define NFSCTL_GETFH		6	/ * get an fh by ino DISCARDED */
 #define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
 #define	NFSCTL_GETFS		8	/* get an fh by path with max FH len */
 
@@ -66,25 +66,6 @@
 	__kernel_gid_t		ex_anon_gid;
 };
 
-/* UGIDUPDATE */
-struct nfsctl_uidmap {
-	char *			ug_ident;
-	__kernel_uid_t		ug_uidbase;
-	int			ug_uidlen;
-	__kernel_uid_t *	ug_udimap;
-	__kernel_gid_t		ug_gidbase;
-	int			ug_gidlen;
-	__kernel_gid_t *	ug_gdimap;
-};
-
-/* GETFH */
-struct nfsctl_fhparm {
-	struct sockaddr		gf_addr;
-	__kernel_dev_t		gf_dev;
-	__kernel_ino_t		gf_ino;
-	int			gf_version;
-};
-
 /* GETFD */
 struct nfsctl_fdparm {
 	struct sockaddr		gd_addr;
@@ -108,16 +89,12 @@
 		struct nfsctl_svc	u_svc;
 		struct nfsctl_client	u_client;
 		struct nfsctl_export	u_export;
-		struct nfsctl_uidmap	u_umap;
-		struct nfsctl_fhparm	u_getfh;
 		struct nfsctl_fdparm	u_getfd;
 		struct nfsctl_fsparm	u_getfs;
 	} u;
 #define ca_svc		u.u_svc
 #define ca_client	u.u_client
 #define ca_export	u.u_export
-#define ca_umap		u.u_umap
-#define ca_getfh	u.u_getfh
 #define ca_getfd	u.u_getfd
 #define	ca_getfs	u.u_getfs
 #define ca_authd	u.u_authd
diff -urN linux-2.5.65-bk4/include/linux/pfkeyv2.h linux-2.5.65-bk5/include/linux/pfkeyv2.h
--- linux-2.5.65-bk4/include/linux/pfkeyv2.h	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk5/include/linux/pfkeyv2.h	Mon Mar 31 12:44:34 2003
@@ -262,6 +262,14 @@
 #define SADB_X_EALG_AESCBC		12
 #define SADB_EALG_MAX			12
 
+/* Compression algorithms */
+#define SADB_X_CALG_NONE		0
+#define SADB_X_CALG_OUI			1
+#define SADB_X_CALG_DEFLATE		2
+#define SADB_X_CALG_LZS			3
+#define SADB_X_CALG_LZJH		4
+#define SADB_X_CALG_MAX			4
+
 /* Extension Header values */
 #define SADB_EXT_RESERVED		0
 #define SADB_EXT_SA			1
diff -urN linux-2.5.65-bk4/include/linux/socket.h linux-2.5.65-bk5/include/linux/socket.h
--- linux-2.5.65-bk4/include/linux/socket.h	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk5/include/linux/socket.h	Mon Mar 31 12:44:34 2003
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
+#include <linux/config.h>		/* for CONFIG_COMPAT */
 #include <linux/linkage.h>
 #include <asm/socket.h>			/* arch-dependent defines	*/
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
@@ -239,18 +240,10 @@
 #define MSG_CMSG_COMPAT	0x80000000	/* This message needs 32 bit fixups */
 #else
 #define MSG_CMSG_COMPAT	0		/* We never have 32 bit fixups */
-#define compat_msghdr	msghdr		/* Needed to avoid compiler hoops */
 #endif
 
-struct compat_msghdr;
-extern int msghdr_from_user_compat_to_kern(struct msghdr *, struct compat_msghdr *);
-extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int);
-extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned);
-extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned);
 extern asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags);
 extern asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned flags);
-extern asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen);
 
 
 
@@ -295,10 +288,6 @@
 extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
 extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
-extern int put_cmsg_compat(struct msghdr*, int level, int type, int len, void *data);
-extern void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr);
-extern int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
-			       unsigned char *stackbuf, int stackbuf_size);
 
 #endif
 #endif /* not kernel and not glibc */
diff -urN linux-2.5.65-bk4/include/linux/swap.h linux-2.5.65-bk5/include/linux/swap.h
--- linux-2.5.65-bk4/include/linux/swap.h	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/include/linux/swap.h	Mon Mar 31 12:44:34 2003
@@ -144,6 +144,9 @@
 /* linux/mm/oom_kill.c */
 extern void out_of_memory(void);
 
+/* linux/mm/memory.c */
+extern void swapin_readahead(swp_entry_t);
+
 /* linux/mm/page_alloc.c */
 extern unsigned long totalram_pages;
 extern unsigned long totalhigh_pages;
diff -urN linux-2.5.65-bk4/include/linux/xfrm.h linux-2.5.65-bk5/include/linux/xfrm.h
--- linux-2.5.65-bk4/include/linux/xfrm.h	Mon Mar 17 13:43:47 2003
+++ linux-2.5.65-bk5/include/linux/xfrm.h	Mon Mar 31 12:44:34 2003
@@ -12,12 +12,7 @@
  */
 typedef union
 {
-	struct {
-		__u32	addr;
-		__u32	mask;	/* Use unused bits to cache mask. */
-	} a4;
-#define xfrm4_addr a4.addr
-#define xfrm4_mask a4.mask
+	__u32		a4;
 	__u32		a6[4];
 } xfrm_address_t;
 
diff -urN linux-2.5.65-bk4/include/net/addrconf.h linux-2.5.65-bk5/include/net/addrconf.h
--- linux-2.5.65-bk4/include/net/addrconf.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/net/addrconf.h	Mon Mar 31 12:44:34 2003
@@ -175,7 +175,7 @@
  *	Hash function taken from net_alias.c
  */
 
-static __inline__ u8 ipv6_addr_hash(struct in6_addr *addr)
+static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr)
 {	
 	__u32 word;
 
@@ -195,7 +195,7 @@
  *	compute link-local solicited-node multicast address
  */
 
-static inline void addrconf_addr_solict_mult(struct in6_addr *addr,
+static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
 					     struct in6_addr *solicited)
 {
 	ipv6_addr_set(solicited,
@@ -219,7 +219,7 @@
 		      __constant_htonl(0x2));
 }
 
-static inline int ipv6_addr_is_multicast(struct in6_addr *addr)
+static inline int ipv6_addr_is_multicast(const struct in6_addr *addr)
 {
 	return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
 }
diff -urN linux-2.5.65-bk4/include/net/compat.h linux-2.5.65-bk5/include/net/compat.h
--- linux-2.5.65-bk4/include/net/compat.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/include/net/compat.h	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,41 @@
+#ifndef NET_COMPAT_H
+#define NET_COMPAT_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_COMPAT)
+
+#include <linux/compat.h>
+
+struct compat_msghdr {
+	compat_uptr_t	msg_name;
+	s32		msg_namelen;
+	compat_uptr_t	msg_iov;
+	compat_size_t	msg_iovlen;
+	compat_uptr_t	msg_control;
+	compat_size_t	msg_controllen;
+	u32		msg_flags;
+};
+
+struct compat_cmsghdr {
+	compat_size_t	cmsg_len;
+	s32		cmsg_level;
+	s32		cmsg_type;
+};
+
+#else /* defined(CONFIG_COMPAT) */
+#define compat_msghdr	msghdr		/* to avoid compiler warnings */
+#endif /* defined(CONFIG_COMPAT) */
+
+extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr *);
+extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int);
+extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned);
+extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned);
+extern asmlinkage long compat_sys_getsockopt(int, int, int, char *, int *);
+extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
+extern int put_compat_msg_controllen(struct msghdr *, struct compat_msghdr *,
+		unsigned long);
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, unsigned char *,
+		int);
+
+#endif /* NET_COMPAT_H */
diff -urN linux-2.5.65-bk4/include/net/compat_socket.h linux-2.5.65-bk5/include/net/compat_socket.h
--- linux-2.5.65-bk4/include/net/compat_socket.h	Mon Mar 17 13:44:01 2003
+++ linux-2.5.65-bk5/include/net/compat_socket.h	Wed Dec 31 16:00:00 1969
@@ -1,67 +0,0 @@
-#ifndef NET_COMPAT_SOCKET_H
-#define NET_COMPAT_SOCKET_H 1
-
-#include <linux/compat.h>
-
-#if defined(CONFIG_COMPAT)
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct compat_msghdr {
-	u32		msg_name;
-	int		msg_namelen;
-	u32		msg_iov;
-	compat_size_t	msg_iovlen;
-	u32		msg_control;
-	compat_size_t	msg_controllen;
-	unsigned	msg_flags;
-};
-
-struct compat_cmsghdr {
-	compat_size_t	cmsg_len;
-	int		cmsg_level;
-	int		cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG_COMPAT_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg_compat_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG_COMPAT_NXTHDR(mhdr, cmsg, cmsglen) cmsg_compat_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG_COMPAT_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG_COMPAT_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))))
-#define CMSG_COMPAT_SPACE(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len))
-#define CMSG_COMPAT_LEN(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len))
-
-#define __CMSG_COMPAT_FIRSTHDR(ctl,len) ((len) >= sizeof(struct compat_cmsghdr) ? \
-				    (struct compat_cmsghdr *)(ctl) : \
-				    (struct compat_cmsghdr *)NULL)
-#define CMSG_COMPAT_FIRSTHDR(msg)	__CMSG_COMPAT_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-static __inline__ struct compat_cmsghdr *__cmsg_compat_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct compat_cmsghdr *__cmsg, int __cmsg_len)
-{
-	struct compat_cmsghdr * __ptr;
-
-	__ptr = (struct compat_cmsghdr *)(((unsigned char *) __cmsg) +
-				     CMSG_COMPAT_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-static __inline__ struct compat_cmsghdr *cmsg_compat_nxthdr (struct msghdr *__msg,
-					    struct compat_cmsghdr *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg_compat_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-#endif /* CONFIG_COMPAT */
-#endif
diff -urN linux-2.5.65-bk4/include/net/ipv6.h linux-2.5.65-bk5/include/net/ipv6.h
--- linux-2.5.65-bk4/include/net/ipv6.h	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk5/include/net/ipv6.h	Mon Mar 31 12:44:34 2003
@@ -203,12 +203,8 @@
 
 extern int			ip6_call_ra_chain(struct sk_buff *skb, int sel);
 
-extern int			ipv6_reassembly(struct sk_buff **skb, int);
-
 extern int			ipv6_parse_hopopts(struct sk_buff *skb, int);
 
-extern int			ipv6_parse_exthdrs(struct sk_buff **skb, int);
-
 extern struct ipv6_txoptions *  ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
 
 extern int ip6_frag_nqueues;
@@ -226,21 +222,21 @@
 					   unsigned int, unsigned int);
 
 
-extern int		ipv6_addr_type(struct in6_addr *addr);
+extern int		ipv6_addr_type(const struct in6_addr *addr);
 
-static inline int ipv6_addr_scope(struct in6_addr *addr)
+static inline int ipv6_addr_scope(const struct in6_addr *addr)
 {
 	return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
 }
 
-static inline int ipv6_addr_cmp(struct in6_addr *a1, struct in6_addr *a2)
+static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
 {
-	return memcmp((void *) a1, (void *) a2, sizeof(struct in6_addr));
+	return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr));
 }
 
-static inline void ipv6_addr_copy(struct in6_addr *a1, struct in6_addr *a2)
+static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
 {
-	memcpy((void *) a1, (void *) a2, sizeof(struct in6_addr));
+	memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr));
 }
 
 #ifndef __HAVE_ARCH_ADDR_SET
@@ -255,7 +251,7 @@
 }
 #endif
 
-static inline int ipv6_addr_any(struct in6_addr *a)
+static inline int ipv6_addr_any(const struct in6_addr *a)
 {
 	return ((a->s6_addr32[0] | a->s6_addr32[1] | 
 		 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 
diff -urN linux-2.5.65-bk4/include/net/protocol.h linux-2.5.65-bk5/include/net/protocol.h
--- linux-2.5.65-bk4/include/net/protocol.h	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk5/include/net/protocol.h	Mon Mar 31 12:44:34 2003
@@ -44,7 +44,7 @@
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 struct inet6_protocol 
 {
-	int	(*handler)(struct sk_buff *skb);
+	int	(*handler)(struct sk_buff **skbp);
 
 	void	(*err_handler)(struct sk_buff *skb,
 			       struct inet6_skb_parm *opt,
diff -urN linux-2.5.65-bk4/include/net/transp_v6.h linux-2.5.65-bk5/include/net/transp_v6.h
--- linux-2.5.65-bk4/include/net/transp_v6.h	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk5/include/net/transp_v6.h	Mon Mar 31 12:44:34 2003
@@ -15,6 +15,14 @@
 
 struct flowi;
 
+/* extention headers */
+extern void				ipv6_hopopts_init(void);
+extern void				ipv6_rthdr_init(void);
+extern void				ipv6_frag_init(void);
+extern void				ipv6_nodata_init(void);
+extern void				ipv6_destopt_init(void);
+
+/* transport protocols */
 extern void				rawv6_init(void);
 extern void				udpv6_init(void);
 extern void				tcpv6_init(void);
diff -urN linux-2.5.65-bk4/include/net/xfrm.h linux-2.5.65-bk5/include/net/xfrm.h
--- linux-2.5.65-bk4/include/net/xfrm.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/net/xfrm.h	Mon Mar 31 12:44:34 2003
@@ -10,8 +10,10 @@
 #include <linux/pfkeyv2.h>
 #include <linux/in6.h>
 
+#include <net/sock.h>
 #include <net/dst.h>
 #include <net/route.h>
+#include <net/ipv6.h>
 #include <net/ip6_fib.h>
 
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
@@ -144,6 +146,51 @@
 	XFRM_STATE_DEAD
 };
 
+struct xfrm_type;
+struct xfrm_dst;
+struct xfrm_policy_afinfo {
+	unsigned short		family;
+	rwlock_t		lock;
+	struct xfrm_type_map	*type_map;
+	struct dst_ops		*dst_ops;
+	void			(*garbage_collect)(void);
+	int			(*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
+	struct dst_entry	*(*find_bundle)(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy);
+	int			(*bundle_create)(struct xfrm_policy *policy, 
+						 struct xfrm_state **xfrm, 
+						 int nx,
+						 struct flowi *fl, 
+						 struct dst_entry **dst_p);
+	void			(*decode_session)(struct sk_buff *skb,
+						  struct flowi *fl);
+};
+
+extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
+extern void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+
+#define XFRM_ACQ_EXPIRES	30
+
+struct xfrm_tmpl;
+struct xfrm_state_afinfo {
+	unsigned short		family;
+	rwlock_t		lock;
+	struct list_head	*state_bydst;
+	struct list_head	*state_byspi;
+	void			(*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
+						struct xfrm_tmpl *tmpl,
+						xfrm_address_t *daddr, xfrm_address_t *saddr);
+	struct xfrm_state	*(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto);
+	struct xfrm_state	*(*find_acq)(u8 mode, u16 reqid, u8 proto, 
+					     xfrm_address_t *daddr, xfrm_address_t *saddr, 
+					     int create);
+};
+
+extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
+extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
+extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
+extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
 struct xfrm_type
 {
@@ -159,9 +206,14 @@
 	u32			(*get_max_size)(struct xfrm_state *, int size);
 };
 
-extern int xfrm_register_type(struct xfrm_type *type);
-extern int xfrm_unregister_type(struct xfrm_type *type);
-extern struct xfrm_type *xfrm_get_type(u8 proto);
+struct xfrm_type_map {
+	rwlock_t		lock;
+	struct xfrm_type	*map[256];
+};
+
+extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
+extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
+extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
 extern void xfrm_put_type(struct xfrm_type *type);
 
 struct xfrm_tmpl
@@ -232,6 +284,47 @@
 extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 
+#define XFRM_FLOWCACHE_HASH_SIZE	1024
+
+static inline u32 __flow_hash4(struct flowi *fl)
+{
+	u32 hash = fl->fl4_src ^ fl->uli_u.ports.sport;
+
+	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
+
+	hash ^= fl->fl4_dst ^ fl->uli_u.ports.dport;
+	hash ^= (hash >> 10);
+	hash ^= (hash >> 20);
+	return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
+}
+
+static inline u32 __flow_hash6(struct flowi *fl)
+{
+	u32 hash = fl->fl6_src->s6_addr32[2] ^
+		   fl->fl6_src->s6_addr32[3] ^ 
+		   fl->uli_u.ports.sport;
+
+	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
+
+	hash ^= fl->fl6_dst->s6_addr32[2] ^
+		fl->fl6_dst->s6_addr32[3] ^ 
+		fl->uli_u.ports.dport;
+	hash ^= (hash >> 10);
+	hash ^= (hash >> 20);
+	return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
+}
+
+static inline u32 flow_hash(struct flowi *fl, unsigned short family)
+{
+	switch (family) {
+	case AF_INET:
+		return __flow_hash4(fl);
+	case AF_INET6:
+		return __flow_hash6(fl);
+	}
+	return 0;	/*XXX*/
+}
+
 extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
@@ -248,6 +341,68 @@
 		__xfrm_policy_destroy(policy);
 }
 
+#define XFRM_DST_HSIZE		1024
+
+static __inline__
+unsigned __xfrm4_dst_hash(xfrm_address_t *addr)
+{
+	unsigned h;
+	h = ntohl(addr->a4);
+	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+	return h;
+}
+
+static __inline__
+unsigned __xfrm6_dst_hash(xfrm_address_t *addr)
+{
+	unsigned h;
+	h = ntohl(addr->a6[2]^addr->a6[3]);
+	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+	return h;
+}
+
+static __inline__
+unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family)
+{
+	switch (family) {
+	case AF_INET:
+		return __xfrm4_dst_hash(addr);
+	case AF_INET6:
+		return __xfrm6_dst_hash(addr);
+	}
+	return 0;
+}
+
+static __inline__
+unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto)
+{
+	unsigned h;
+	h = ntohl(addr->a4^spi^proto);
+	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+	return h;
+}
+
+static __inline__
+unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto)
+{
+	unsigned h;
+	h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto);
+	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+	return h;
+}
+
+static __inline__
+unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family)
+{
+	switch (family) {
+	case AF_INET:
+		return __xfrm4_spi_hash(addr, spi, proto);
+	case AF_INET6:
+		return __xfrm6_spi_hash(addr, spi, proto);
+	}
+	return 0;	/*XXX*/
+}
+
 extern void __xfrm_state_destroy(struct xfrm_state *);
 
 static inline void xfrm_state_put(struct xfrm_state *x)
@@ -261,15 +416,65 @@
 	atomic_inc(&x->refcnt);
 }
 
+static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
+{
+	__u32 *a1 = token1;
+	__u32 *a2 = token2;
+	int pdw;
+	int pbi;
+
+	pdw = prefixlen >> 5;	  /* num of whole __u32 in prefix */
+	pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
+
+	if (pdw)
+		if (memcmp(a1, a2, pdw << 2))
+			return 0;
+
+	if (pbi) {
+		__u32 mask;
+
+		mask = htonl((0xffffffff) << (32 - pbi));
+
+		if ((a1[pdw] ^ a2[pdw]) & mask)
+			return 0;
+	}
+
+	return 1;
+}
+
+static inline int
+__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
+{
+	return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
+		addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
+		!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
+		!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
+		(fl->proto == sel->proto || !sel->proto) &&
+		(fl->oif == sel->ifindex || !sel->ifindex);
+}
+
 static inline int
-xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
+__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
-	return	!((fl->fl4_dst^sel->daddr.xfrm4_addr)&sel->daddr.xfrm4_mask) &&
+	return  addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
+		addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
 		!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
 		!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
-		(fl->oif == sel->ifindex || !sel->ifindex) &&
-		!((fl->fl4_src^sel->saddr.xfrm4_addr)&sel->saddr.xfrm4_mask);
+		(fl->oif == sel->ifindex || !sel->ifindex);
+}
+
+static inline int
+xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
+		    unsigned short family)
+{
+	switch (family) {
+	case AF_INET:
+		return __xfrm4_selector_match(sel, fl);
+	case AF_INET6:
+		return __xfrm6_selector_match(sel, fl);
+	}
+	return 0;
 }
 
 /* A struct encoding bundle of transformations to apply to some set of flow.
@@ -295,6 +500,7 @@
 
 struct sec_path
 {
+	kmem_cache_t		*pool;
 	atomic_t		refcnt;
 	int			len;
 	struct xfrm_state	*xvec[XFRM_MAX_DEPTH];
@@ -316,42 +522,73 @@
 	if (sp && atomic_dec_and_test(&sp->refcnt))
 		__secpath_destroy(sp);
 }
+
+static inline int
+__xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+{
+	return	(tmpl->saddr.a4 &&
+		 tmpl->saddr.a4 != x->props.saddr.a4);
+}
+
+static inline int
+__xfrm6_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+{
+	return	(!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) &&
+		 ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
+}
+
+static inline int
+xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short family)
+{
+	switch (family) {
+	case AF_INET:
+		return __xfrm4_state_addr_cmp(tmpl, x);
+	case AF_INET6:
+		return __xfrm6_state_addr_cmp(tmpl, x);
+	}
+	return !0;
+}
+
 extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
 
-static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
 {
 	if (sk && sk->policy[XFRM_POLICY_IN])
-		return __xfrm_policy_check(sk, dir, skb, AF_INET);
+		return __xfrm_policy_check(sk, dir, skb, family);
 		
 	return	!xfrm_policy_list[dir] ||
 		(skb->dst->flags & DST_NOPOLICY) ||
-		__xfrm_policy_check(sk, dir, skb, AF_INET);
+		__xfrm_policy_check(sk, dir, skb, family);
+}
+
+static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+	return xfrm_policy_check(sk, dir, skb, AF_INET);
 }
 
 static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
 {
-	if (sk && sk->policy[XFRM_POLICY_IN])
-		return __xfrm_policy_check(sk, dir, skb, AF_INET6);
-		
-	return	!xfrm_policy_list[dir] ||
-		(skb->dst->flags & DST_NOPOLICY) ||
-		__xfrm_policy_check(sk, dir, skb, AF_INET6);
+	return xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
 
+
 extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
 
-static inline int xfrm_route_forward(struct sk_buff *skb)
+static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 {
 	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
 		(skb->dst->flags & DST_NOXFRM) ||
-		__xfrm_route_forward(skb, AF_INET);
+		__xfrm_route_forward(skb, family);
+}
+
+static inline int xfrm4_route_forward(struct sk_buff *skb)
+{
+	return xfrm_route_forward(skb, AF_INET);
 }
 
 static inline int xfrm6_route_forward(struct sk_buff *skb)
 {
-	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
-		(skb->dst->flags & DST_NOXFRM) ||
-		__xfrm_route_forward(skb, AF_INET6);
+	return xfrm_route_forward(skb, AF_INET6);
 }
 
 extern int __xfrm_sk_clone_policy(struct sock *sk);
@@ -377,6 +614,66 @@
 	}
 }
 
+static __inline__
+xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family)
+{
+	switch (family){
+	case AF_INET:
+		return (xfrm_address_t *)&fl->fl4_dst;
+	case AF_INET6:
+		return (xfrm_address_t *)fl->fl6_dst;
+	}
+	return NULL;
+}
+
+static __inline__
+xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
+{
+	switch (family){
+	case AF_INET:
+		return (xfrm_address_t *)&fl->fl4_src;
+	case AF_INET6:
+		return (xfrm_address_t *)fl->fl6_src;
+	}
+	return NULL;
+}
+
+static __inline__ int
+__xfrm4_state_addr_check(struct xfrm_state *x,
+			 xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
+	if (daddr->a4 == x->id.daddr.a4 &&
+	    (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4))
+		return 1;
+	return 0;
+}
+
+static __inline__ int
+__xfrm6_state_addr_check(struct xfrm_state *x,
+			 xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
+	if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) &&
+	    (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)|| 
+	     ipv6_addr_any((struct in6_addr *)saddr) || 
+	     ipv6_addr_any((struct in6_addr *)&x->props.saddr)))
+		return 1;
+	return 0;
+}
+
+static __inline__ int
+xfrm_state_addr_check(struct xfrm_state *x,
+		      xfrm_address_t *daddr, xfrm_address_t *saddr,
+		      unsigned short family)
+{
+	switch (family) {
+	case AF_INET:
+		return __xfrm4_state_addr_check(x, daddr, saddr);
+	case AF_INET6:
+		return __xfrm6_state_addr_check(x, daddr, saddr);
+	}
+	return 0;
+}
+
 /*
  * xfrm algorithm information
  */
@@ -390,30 +687,42 @@
 	u16 defkeybits;
 };
 
+struct xfrm_algo_comp_info {
+	u16 threshold;
+};
+
 struct xfrm_algo_desc {
 	char *name;
 	u8 available:1;
 	union {
 		struct xfrm_algo_auth_info auth;
 		struct xfrm_algo_encr_info encr;
+		struct xfrm_algo_comp_info comp;
 	} uinfo;
 	struct sadb_alg desc;
 };
 
+extern void xfrm_init(void);
+extern void xfrm4_init(void);
+extern void xfrm4_fini(void);
+extern void xfrm6_init(void);
+extern void xfrm6_fini(void);
 extern void xfrm_state_init(void);
-extern void xfrm_input_init(void);
+extern void xfrm4_state_init(void);
+extern void xfrm4_state_fini(void);
+extern void xfrm6_state_init(void);
+extern void xfrm6_state_fini(void);
+
 extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 extern struct xfrm_state *xfrm_state_alloc(void);
-extern struct xfrm_state *xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-					   struct xfrm_policy *pol, int *err);
-extern struct xfrm_state *xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr,
-					   struct flowi *fl, struct xfrm_tmpl *tmpl,
-					   struct xfrm_policy *pol, int *err);
+extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 
+					  struct flowi *fl, struct xfrm_tmpl *tmpl,
+					  struct xfrm_policy *pol, int *err,
+					  unsigned short family);
 extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
-extern struct xfrm_state *xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto);
-extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto);
+extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern void xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
@@ -421,10 +730,13 @@
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
 extern int xfrm4_rcv(struct sk_buff *skb);
-extern int xfrm6_rcv(struct sk_buff *skb);
+extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen);
 
+void xfrm_policy_init(void);
+void xfrm4_policy_init(void);
+void xfrm6_policy_init(void);
 struct xfrm_policy *xfrm_policy_alloc(int gfp);
 extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
 struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, unsigned short family);
@@ -433,76 +745,39 @@
 struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
 void xfrm_policy_flush(void);
 void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create);
-struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr,
-				   struct in6_addr *saddr, int create);
+struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, 
+				  xfrm_address_t *daddr, xfrm_address_t *saddr, 
+				  int create, unsigned short family);
 extern void xfrm_policy_flush(void);
 extern void xfrm_policy_kill(struct xfrm_policy *);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl);
 extern int xfrm_flush_bundles(struct xfrm_state *x);
+extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 
 extern wait_queue_head_t km_waitq;
 extern void km_warn_expired(struct xfrm_state *x);
 extern void km_expired(struct xfrm_state *x);
 extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
 
+extern void xfrm4_input_init(void);
+extern void xfrm6_input_init(void);
+extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq);
+
 extern void xfrm_probe_algs(void);
 extern int xfrm_count_auth_supported(void);
 extern int xfrm_count_enc_supported(void);
 extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
+extern struct xfrm_algo_desc *xfrm_calg_get_byidx(unsigned int idx);
 extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
+extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
 extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
-
-static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
-{
-	__u32 *a1 = token1;
-	__u32 *a2 = token2;
-	int pdw;
-	int pbi;
-
-	pdw = prefixlen >> 5;	  /* num of whole __u32 in prefix */
-	pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
-
-	if (pdw)
-		if (memcmp(a1, a2, pdw << 2))
-			return 0;
-
-	if (pbi) {
-		__u32 mask;
-
-		mask = htonl((0xffffffff) << (32 - pbi));
-
-		if ((a1[pdw] ^ a2[pdw]) & mask)
-			return 0;
-	}
-
-	return 1;
-}
-
-static inline int
-xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
-{
-	return  addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
-		addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
-		!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
-		(fl->proto == sel->proto || !sel->proto) &&
-		(fl->oif == sel->ifindex || !sel->ifindex);
-}
-
-extern int xfrm6_register_type(struct xfrm_type *type);
-extern int xfrm6_unregister_type(struct xfrm_type *type);
-extern struct xfrm_type *xfrm6_get_type(u8 proto);
+extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name);
 
 struct crypto_tfm;
 typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int);
 
-typedef int (xfrm_dst_lookup_t)(struct xfrm_dst **dst, struct flowi *fl);
-int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, unsigned short family);
-void xfrm_dst_lookup_unregister(unsigned short family);
-
 #endif	/* _NET_XFRM_H */
diff -urN linux-2.5.65-bk4/include/pcmcia/ds.h linux-2.5.65-bk5/include/pcmcia/ds.h
--- linux-2.5.65-bk4/include/pcmcia/ds.h	Mon Mar 31 12:44:29 2003
+++ linux-2.5.65-bk5/include/pcmcia/ds.h	Mon Mar 31 12:44:34 2003
@@ -141,9 +141,6 @@
 
 int unregister_pccard_driver(dev_info_t *dev_info);
 
-#define register_pcmcia_driver register_pccard_driver
-#define unregister_pcmcia_driver unregister_pccard_driver
-
 extern struct bus_type pcmcia_bus_type;
 
 struct pcmcia_driver {
diff -urN linux-2.5.65-bk4/kernel/posix-timers.c linux-2.5.65-bk5/kernel/posix-timers.c
--- linux-2.5.65-bk4/kernel/posix-timers.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/kernel/posix-timers.c	Mon Mar 31 12:44:34 2003
@@ -1,12 +1,12 @@
 /*
  * linux/kernel/posix_timers.c
  *
- * 
+ *
  * 2002-10-15  Posix Clocks & timers by George Anzinger
  *			     Copyright (C) 2002 by MontaVista Software.
  */
 
-/* These are all the functions necessary to implement 
+/* These are all the functions necessary to implement
  * POSIX clocks & timers
  */
 #include <linux/mm.h>
@@ -32,28 +32,28 @@
 		       *remainder = do_div(result,divisor); \
 		       result; })
 
-#endif				/* ifndef div_long_long_rem */
+#endif
 
 /*
  * Management arrays for POSIX timers.	 Timers are kept in slab memory
  * Timer ids are allocated by an external routine that keeps track of the
  * id and the timer.  The external interface is:
  *
- *void *idr_find(struct idr *idp, int id);           to find timer_id <id>
- *int idr_get_new(struct idr *idp, void *ptr);       to get a new id and 
- *                                                  related it to <ptr>
- *void idr_remove(struct idr *idp, int id);          to release <id>
- *void idr_init(struct idr *idp);                    to initialize <idp>
- *                                                  which we supply.
+ * void *idr_find(struct idr *idp, int id);           to find timer_id <id>
+ * int idr_get_new(struct idr *idp, void *ptr);       to get a new id and
+ *                                                    related it to <ptr>
+ * void idr_remove(struct idr *idp, int id);          to release <id>
+ * void idr_init(struct idr *idp);                    to initialize <idp>
+ *                                                    which we supply.
  * The idr_get_new *may* call slab for more memory so it must not be
  * called under a spin lock.  Likewise idr_remore may release memory
  * (but it may be ok to do this under a lock...).
  * idr_find is just a memory look up and is quite fast.  A zero return
  * indicates that the requested id does not exist.
-
  */
+
 /*
-   * Lets keep our timers in a slab cache :-)
+ * Lets keep our timers in a slab cache :-)
  */
 static kmem_cache_t *posix_timers_cache;
 static struct idr posix_timers_id;
@@ -65,24 +65,28 @@
  */
 #define TIMER_INACTIVE 1
 #define TIMER_RETRY 1
+
 #ifdef CONFIG_SMP
-#define timer_active(tmr) (tmr->it_timer.entry.prev != (void *)TIMER_INACTIVE)
-#define set_timer_inactive(tmr) tmr->it_timer.entry.prev = (void *)TIMER_INACTIVE
+# define timer_active(tmr) \
+		((tmr)->it_timer.entry.prev != (void *)TIMER_INACTIVE)
+# define set_timer_inactive(tmr) \
+		do { \
+			(tmr)->it_timer.entry.prev = (void *)TIMER_INACTIVE; \
+		} while (0)
 #else
-#define timer_active(tmr) BARFY	// error to use outside of SMP
-#define set_timer_inactive(tmr)
+# define timer_active(tmr) BARFY	// error to use outside of SMP
+# define set_timer_inactive(tmr) do { } while (0)
 #endif
 /*
  * The timer ID is turned into a timer address by idr_find().
  * Verifying a valid ID consists of:
- * 
+ *
  * a) checking that idr_find() returns other than zero.
  * b) checking that the timer id matches the one in the timer itself.
  * c) that the timer owner is in the callers thread group.
  */
 
-
-/* 
+/*
  * CLOCKs: The POSIX standard calls for a couple of clocks and allows us
  *	    to implement others.  This structure defines the various
  *	    clocks and allows the possibility of adding others.	 We
@@ -90,7 +94,7 @@
  *	    the "arch" code to add at least one clock that is high
  *	    resolution.	 Here we define the standard CLOCK_REALTIME as a
  *	    1/HZ resolution clock.
-
+ *
  * CPUTIME & THREAD_CPUTIME: We are not, at this time, definding these
  *	    two clocks (and the other process related clocks (Std
  *	    1003.1d-1999).  The way these should be supported, we think,
@@ -98,7 +102,7 @@
  *	    pinned to the executing process and to use -pid for clocks
  *	    pinned to particular pids.	Calls which supported these clock
  *	    ids would split early in the function.
- 
+ *
  * RESOLUTION: Clock resolution is used to round up timer and interval
  *	    times, NOT to report clock times, which are reported with as
  *	    much resolution as the system can muster.  In some cases this
@@ -106,7 +110,7 @@
  *	    may not be quantifiable until run time, and only then is the
  *	    necessary code is written.	The standard says we should say
  *	    something about this issue in the documentation...
-
+ *
  * FUNCTIONS: The CLOCKs structure defines possible functions to handle
  *	    various clock functions.  For clocks that use the standard
  *	    system timer code these entries should be NULL.  This will
@@ -116,7 +120,7 @@
  *	    ENOSYS.  The standard POSIX timer management code assumes the
  *	    following: 1.) The k_itimer struct (sched.h) is used for the
  *	    timer.  2.) The list, it_lock, it_clock, it_id and it_process
- *	    fields are not modified by timer code. 
+ *	    fields are not modified by timer code.
  *
  *          At this time all functions EXCEPT clock_nanosleep can be
  *          redirected by the CLOCKS structure.  Clock_nanosleep is in
@@ -132,37 +136,29 @@
 
 static struct k_clock posix_clocks[MAX_CLOCKS];
 
-#define if_clock_do(clock_fun, alt_fun,parms)	(! clock_fun)? alt_fun parms :\
-							      clock_fun parms
+#define if_clock_do(clock_fun,alt_fun,parms) \
+		(!clock_fun) ? alt_fun parms : clock_fun parms
 
-#define p_timer_get( clock,a,b) if_clock_do((clock)->timer_get, \
-					     do_timer_gettime,	 \
-					     (a,b))
-
-#define p_nsleep( clock,a,b,c) if_clock_do((clock)->nsleep,   \
-					    do_nsleep,	       \
-					    (a,b,c))
-
-#define p_timer_del( clock,a) if_clock_do((clock)->timer_del, \
-					   do_timer_delete,    \
-					   (a))
+#define p_timer_get(clock,a,b) \
+	       	if_clock_do((clock)->timer_get,do_timer_gettime, (a,b))
 
-void register_posix_clock(int clock_id, struct k_clock *new_clock);
+#define p_nsleep(clock,a,b,c) \
+		if_clock_do((clock)->nsleep, do_nsleep, (a,b,c))
 
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp);
+#define p_timer_del(clock,a) \
+		if_clock_do((clock)->timer_del, do_timer_delete, (a))
 
+void register_posix_clock(int clock_id, struct k_clock *new_clock);
+static int do_posix_gettime(struct k_clock *clock, struct timespec *tp);
 int do_posix_clock_monotonic_gettime(struct timespec *tp);
-
 int do_posix_clock_monotonic_settime(struct timespec *tp);
 static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
 static inline void unlock_timer(struct k_itimer *timr, unsigned long flags);
 
-/* 
+/*
  * Initialize everything, well, just everything in Posix clocks/timers ;)
  */
-
-static __init int
-init_posix_timers(void)
+static __init int init_posix_timers(void)
 {
 	struct k_clock clock_realtime = {.res = NSEC_PER_SEC / HZ };
 	struct k_clock clock_monotonic = {.res = NSEC_PER_SEC / HZ,
@@ -174,9 +170,9 @@
 	register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
 
 	posix_timers_cache = kmem_cache_create("posix_timers_cache",
-					       sizeof (struct k_itimer), 0, 0,
-					       0, 0);
+					sizeof (struct k_itimer), 0, 0, 0, 0);
 	idr_init(&posix_timers_id);
+
 	return 0;
 }
 
@@ -200,11 +196,11 @@
 	 * unsigned int/2).  Times beyond this will be truncated back to
 	 * this value.   This is done in the absolute adjustment code,
 	 * below.  Here it is enough to just discard the high order
-	 * bits.  
+	 * bits.
 	 */
 	*jiff = (u64)sec * HZ;
 	/*
-	 * Do the res thing. (Don't forget the add in the declaration of nsec) 
+	 * Do the res thing. (Don't forget the add in the declaration of nsec)
 	 */
 	nsec -= nsec % res;
 	/*
@@ -213,8 +209,7 @@
 	*jiff += nsec / (NSEC_PER_SEC / HZ);
 }
 
-static void
-tstotimer(struct itimerspec *time, struct k_itimer *timer)
+static void tstotimer(struct itimerspec *time, struct k_itimer *timer)
 {
 	u64 result;
 	int res = posix_clocks[timer->it_clock].res;
@@ -225,22 +220,18 @@
 	timer->it_incr = (unsigned long)result;
 }
 
-static void
-schedule_next_timer(struct k_itimer *timr)
+static void schedule_next_timer(struct k_itimer *timr)
 {
 	struct now_struct now;
 
 	/* Set up the timer for the next interval (if there is one) */
-	if (timr->it_incr == 0) {
-		{
-			set_timer_inactive(timr);
-			return;
-		}
+	if (!timr->it_incr) {
+		set_timer_inactive(timr);
+		return;
 	}
 	posix_get_now(&now);
-	while (posix_time_before(&timr->it_timer, &now)) {
+	while (posix_time_before(&timr->it_timer, &now))
 		posix_bump_timer(timr);
-	};
 	timr->it_overrun_last = timr->it_overrun;
 	timr->it_overrun = -1;
 	timr->it_requeue_pending = 0;
@@ -248,7 +239,6 @@
 }
 
 /*
-
  * This function is exported for use by the signal deliver code.  It is
  * called just prior to the info block being released and passes that
  * block to us.  It's function is to update the overrun entry AND to
@@ -258,12 +248,9 @@
  *
  * To protect aginst the timer going away while the interrupt is queued,
  * we require that the it_requeue_pending flag be set.
-
  */
-void
-do_schedule_next_timer(struct siginfo *info)
+void do_schedule_next_timer(struct siginfo *info)
 {
-
 	struct k_itimer *timr;
 	unsigned long flags;
 
@@ -274,13 +261,12 @@
 
 	schedule_next_timer(timr);
 	info->si_overrun = timr->it_overrun_last;
-      exit:
+exit:
 	if (timr)
 		unlock_timer(timr, flags);
 }
 
-/* 
-
+/*
  * Notify the task and set up the timer for the next expiration (if
  * applicable).  This function requires that the k_itimer structure
  * it_lock is taken.  This code will requeue the timer only if we get
@@ -288,11 +274,9 @@
  * indicating that the signal was either not queued or was queued
  * without an info block.  In this case, we will not get a call back to
  * do_schedule_next_timer() so we do it here.  This should be rare...
-
  */
 
-static void
-timer_notify_task(struct k_itimer *timr)
+static void timer_notify_task(struct k_itimer *timr)
 {
 	struct siginfo info;
 	int ret;
@@ -305,11 +289,11 @@
 	info.si_code = SI_TIMER;
 	info.si_tid = timr->it_id;
 	info.si_value = timr->it_sigev_value;
-	if (timr->it_incr == 0) {
+	if (!timr->it_incr)
 		set_timer_inactive(timr);
-	} else {
+	else
 		timr->it_requeue_pending = info.si_sys_private = 1;
-	}
+
 	ret = send_sig_info(info.si_signo, &info, timr->it_process);
 	switch (ret) {
 
@@ -324,11 +308,11 @@
 		 * signal was not sent because of sig_ignor or,
 		 * possibly no queue memory OR will be sent but,
 		 * we will not get a call back to restart it AND
-		 * it should be restarted. 
+		 * it should be restarted.
 		 */
 		schedule_next_timer(timr);
 	case 0:
-		/* 
+		/*
 		 * all's well new signal queued
 		 */
 		break;
@@ -336,14 +320,11 @@
 }
 
 /*
-
  * This function gets called when a POSIX.1b interval timer expires.  It
  * is used as a callback from the kernel internal timer.  The
  * run_timer_list code ALWAYS calls with interrutps on.
-
  */
-static void
-posix_timer_fn(unsigned long __data)
+static void posix_timer_fn(unsigned long __data)
 {
 	struct k_itimer *timr = (struct k_itimer *) __data;
 	unsigned long flags;
@@ -354,8 +335,8 @@
 }
 
 /*
- * For some reason mips/mips64 define the SIGEV constants plus 128.  
- * Here we define a mask to get rid of the common bits.	 The 
+ * For some reason mips/mips64 define the SIGEV constants plus 128.
+ * Here we define a mask to get rid of the common bits.	 The
  * optimizer should make this costless to all but mips.
  */
 #if (ARCH == mips) || (ARCH == mips64)
@@ -367,30 +348,26 @@
 #define MIPS_SIGEV (int)-1
 #endif
 
-static inline struct task_struct *
-good_sigevent(sigevent_t * event)
+static inline struct task_struct * good_sigevent(sigevent_t * event)
 {
 	struct task_struct *rtn = current;
 
-	if (event->sigev_notify & SIGEV_THREAD_ID & MIPS_SIGEV) {
-		if (!(rtn =
-		      find_task_by_pid(event->sigev_notify_thread_id)) ||
-		    rtn->tgid != current->tgid) {
-			return NULL;
-		}
-	}
-	if (event->sigev_notify & SIGEV_SIGNAL & MIPS_SIGEV) {
-		if ((unsigned) (event->sigev_signo > SIGRTMAX))
-			return NULL;
-	}
-	if (event->sigev_notify & ~(SIGEV_SIGNAL | SIGEV_THREAD_ID)) {
+	if ((event->sigev_notify & SIGEV_THREAD_ID & MIPS_SIGEV) &&
+		(!(rtn = find_task_by_pid(event->sigev_notify_thread_id)) ||
+			rtn->tgid != current->tgid))
 		return NULL;
-	}
+
+	if ((event->sigev_notify & SIGEV_SIGNAL & MIPS_SIGEV) &&
+			((unsigned) (event->sigev_signo > SIGRTMAX)))
+		return NULL;
+
+	if (event->sigev_notify & ~(SIGEV_SIGNAL | SIGEV_THREAD_ID))
+		return NULL;
+
 	return rtn;
 }
 
-void
-register_posix_clock(int clock_id, struct k_clock *new_clock)
+void register_posix_clock(int clock_id, struct k_clock *new_clock)
 {
 	if ((unsigned) clock_id >= MAX_CLOCKS) {
 		printk("POSIX clock register failed for clock_id %d\n",
@@ -400,19 +377,18 @@
 	posix_clocks[clock_id] = *new_clock;
 }
 
-static struct k_itimer *
-alloc_posix_timer(void)
+static struct k_itimer * alloc_posix_timer(void)
 {
 	struct k_itimer *tmr;
 	tmr = kmem_cache_alloc(posix_timers_cache, GFP_KERNEL);
 	memset(tmr, 0, sizeof (struct k_itimer));
-	return (tmr);
+
+	return tmr;
 }
 
-static void
-release_posix_timer(struct k_itimer *tmr)
+static void release_posix_timer(struct k_itimer *tmr)
 {
-	if (tmr->it_id != -1){
+	if (tmr->it_id != -1) {
 		spin_lock_irq(&idr_lock);
 		idr_remove(&posix_timers_id, tmr->it_id);
 		spin_unlock_irq(&idr_lock);
@@ -422,7 +398,7 @@
 
 /* Create a POSIX.1b interval timer. */
 
-asmlinkage int
+asmlinkage long
 sys_timer_create(clockid_t which_clock,
 		 struct sigevent *timer_event_spec, timer_t * created_timer_id)
 {
@@ -433,28 +409,29 @@
 	sigevent_t event;
 
 	if ((unsigned) which_clock >= MAX_CLOCKS ||
-	    !posix_clocks[which_clock].res) return -EINVAL;
+				!posix_clocks[which_clock].res)
+		return -EINVAL;
 
 	new_timer = alloc_posix_timer();
-	if (unlikely (new_timer == NULL))
+	if (unlikely(!new_timer))
 		return -EAGAIN;
 
 	spin_lock_init(&new_timer->it_lock);
 	do {
-		if ( unlikely ( !idr_pre_get(&posix_timers_id))){
+		if (unlikely(!idr_pre_get(&posix_timers_id))) {
 			error = -EAGAIN;
 			new_timer_id = (timer_t)-1;
-			goto out;			
+			goto out;
 		}
 		spin_lock_irq(&idr_lock);
-		new_timer_id = (timer_t) idr_get_new(
-			&posix_timers_id, (void *) new_timer);
+		new_timer_id = (timer_t) idr_get_new(&posix_timers_id,
+							(void *) new_timer);
 		spin_unlock_irq(&idr_lock);
-	}while( unlikely (new_timer_id == -1));
+	} while (unlikely(new_timer_id == -1));
 
 	new_timer->it_id = new_timer_id;
 	/*
-	 * return the timer_id now.  The next step is hard to 
+	 * return the timer_id now.  The next step is hard to
 	 * back out if there is an error.
 	 */
 	if (copy_to_user(created_timer_id,
@@ -470,13 +447,12 @@
 		read_lock(&tasklist_lock);
 		if ((process = good_sigevent(&event))) {
 			/*
-
 			 * We may be setting up this process for another
-			 * thread.  It may be exitiing.  To catch this
+			 * thread.  It may be exiting.  To catch this
 			 * case the we check the PF_EXITING flag.  If
 			 * the flag is not set, the task_lock will catch
 			 * him before it is too late (in exit_itimers).
-
+			 *
 			 * The exec case is a bit more invloved but easy
 			 * to code.  If the process is in our thread
 			 * group (and it must be or we would not allow
@@ -484,7 +460,6 @@
 			 * us to be killed.  In this case it will wait
 			 * for us to die which means we can finish this
 			 * linkage with our last gasp. I.e. no code :)
-
 			 */
 			task_lock(process);
 			if (!(process->flags & PF_EXITING)) {
@@ -527,11 +502,10 @@
 	 * Once we set the process, it can be found so do it last...
 	 */
 	new_timer->it_process = process;
-
-      out:
-	if (error) {
+out:
+	if (error)
 		release_posix_timer(new_timer);
-	}
+
 	return error;
 }
 
@@ -543,43 +517,36 @@
  * Arguments:
  * ts	     : Pointer to the timespec structure to check
  *
- * Return value: 
+ * Return value:
  * If a NULL pointer was passed in, or the tv_nsec field was less than 0
  * or greater than NSEC_PER_SEC, or the tv_sec field was less than 0,
  * this function returns 0. Otherwise it returns 1.
-
  */
-
-static int
-good_timespec(const struct timespec *ts)
+static int good_timespec(const struct timespec *ts)
 {
-	if ((ts == NULL) ||
-	    (ts->tv_sec < 0) ||
-	    ((unsigned) ts->tv_nsec >= NSEC_PER_SEC)) return 0;
+	if ((!ts) || (ts->tv_sec < 0) ||
+			((unsigned) ts->tv_nsec >= NSEC_PER_SEC))
+		return 0;
 	return 1;
 }
 
-static inline void
-unlock_timer(struct k_itimer *timr, unsigned long flags)
+static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
 {
 	spin_unlock_irqrestore(&timr->it_lock, flags);
 }
 
 /*
-
  * Locking issues: We need to protect the result of the id look up until
  * we get the timer locked down so it is not deleted under us.  The
  * removal is done under the idr spinlock so we use that here to bridge
  * the find to the timer lock.  To avoid a dead lock, the timer id MUST
  * be release with out holding the timer lock.
-
  */
-static struct k_itimer *
-lock_timer(timer_t timer_id, unsigned long *flags)
+static struct k_itimer * lock_timer(timer_t timer_id, unsigned long *flags)
 {
 	struct k_itimer *timr;
 	/*
-	 * Watch out here.  We do a irqsave on the idr_lock and pass the 
+	 * Watch out here.  We do a irqsave on the idr_lock and pass the
 	 * flags part over to the timer lock.  Must not let interrupts in
 	 * while we are moving the lock.
 	 */
@@ -590,35 +557,32 @@
 		spin_lock(&timr->it_lock);
 		spin_unlock(&idr_lock);
 
-		if ( (timr->it_id != timer_id) || !(timr->it_process) ||
-		     timr->it_process->tgid != current->tgid) {
+		if ((timr->it_id != timer_id) || !(timr->it_process) ||
+				timr->it_process->tgid != current->tgid) {
 			unlock_timer(timr, *flags);
 			timr = NULL;
 		}
-	} else {
+	} else
 		spin_unlock_irqrestore(&idr_lock, *flags);
-	}
 
 	return timr;
 }
 
-/* 
-
+/*
  * Get the time remaining on a POSIX.1b interval timer.  This function
  * is ALWAYS called with spin_lock_irq on the timer, thus it must not
  * mess with irq.
-
+ *
  * We have a couple of messes to clean up here.  First there is the case
  * of a timer that has a requeue pending.  These timers should appear to
  * be in the timer list with an expiry as if we were to requeue them
  * now.
-
+ *
  * The second issue is the SIGEV_NONE timer which may be active but is
  * not really ever put in the timer list (to save system resources).
  * This timer may be expired, and if so, we will do it here.  Otherwise
  * it is the same as a requeue pending timer WRT to what we should
  * report.
-
  */
 void inline
 do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting)
@@ -627,31 +591,25 @@
 	unsigned long expires;
 	struct now_struct now;
 
-	do {
+	do
 		expires = timr->it_timer.expires;
-	} while ((volatile long) (timr->it_timer.expires) != expires);
+	while ((volatile long) (timr->it_timer.expires) != expires);
 
 	posix_get_now(&now);
 
-	if (expires && (timr->it_sigev_notify & SIGEV_NONE) && !timr->it_incr) {
-		if (posix_time_before(&timr->it_timer, &now)) {
-			timr->it_timer.expires = expires = 0;
-		}
-	}
+	if (expires && (timr->it_sigev_notify & SIGEV_NONE) && !timr->it_incr &&
+			posix_time_before(&timr->it_timer, &now))
+		timr->it_timer.expires = expires = 0;
 	if (expires) {
 		if (timr->it_requeue_pending ||
-		    (timr->it_sigev_notify & SIGEV_NONE)) {
-			while (posix_time_before(&timr->it_timer, &now)) {
+		    (timr->it_sigev_notify & SIGEV_NONE))
+			while (posix_time_before(&timr->it_timer, &now))
 				posix_bump_timer(timr);
-			};
-		} else {
-			if (!timer_pending(&timr->it_timer)) {
+		else
+			if (!timer_pending(&timr->it_timer))
 				sub_expires = expires = 0;
-			}
-		}
-		if (expires) {
+		if (expires)
 			expires -= now.jiffies;
-		}
 	}
 	jiffies_to_timespec(expires, &cur_setting->it_value);
 	jiffies_to_timespec(timr->it_incr, &cur_setting->it_interval);
@@ -661,8 +619,9 @@
 		cur_setting->it_value.tv_sec = 0;
 	}
 }
+
 /* Get the time remaining on a POSIX.1b interval timer. */
-asmlinkage int
+asmlinkage long
 sys_timer_gettime(timer_t timer_id, struct itimerspec *setting)
 {
 	struct k_itimer *timr;
@@ -683,7 +642,6 @@
 	return 0;
 }
 /*
-
  * Get the number of overruns of a POSIX.1b interval timer.  This is to
  * be the overrun of the timer last delivered.  At the same time we are
  * accumulating overruns on the next timer.  The overrun is frozen when
@@ -691,10 +649,9 @@
  * is not queued) or at the actual delivery time (as we are informed by
  * the call back to do_schedule_next_timer().  So all we need to do is
  * to pick up the frozen overrun.
-
  */
 
-asmlinkage int
+asmlinkage long
 sys_timer_getoverrun(timer_t timer_id)
 {
 	struct k_itimer *timr;
@@ -710,8 +667,9 @@
 
 	return overrun;
 }
-/* Adjust for absolute time */
 /*
+ * Adjust for absolute time
+ *
  * If absolute time is given and it is not CLOCK_MONOTONIC, we need to
  * adjust for the offset between the timer clock (CLOCK_MONOTONIC) and
  * what ever clock he is using.
@@ -719,26 +677,23 @@
  * If it is relative time, we need to add the current (CLOCK_MONOTONIC)
  * time to it to get the proper time for the timer.
  */
-static int
-adjust_abs_time(struct k_clock *clock, struct timespec *tp, int abs)
+static int adjust_abs_time(struct k_clock *clock, struct timespec *tp, int abs)
 {
 	struct timespec now;
 	struct timespec oc;
 	do_posix_clock_monotonic_gettime(&now);
 
-	if (abs &&
-	    (posix_clocks[CLOCK_MONOTONIC].clock_get == clock->clock_get)) {
-	} else {
-
-		if (abs) {
+	if (!abs || (posix_clocks[CLOCK_MONOTONIC].clock_get !=
+							clock->clock_get)) {
+		if (abs)
 			do_posix_gettime(clock, &oc);
-		} else {
+		else
 			oc.tv_nsec = oc.tv_sec = 0;
-		}
+
 		tp->tv_sec += now.tv_sec - oc.tv_sec;
 		tp->tv_nsec += now.tv_nsec - oc.tv_nsec;
 
-		/* 
+		/*
 		 * Normalize...
 		 */
 		if ((tp->tv_nsec - NSEC_PER_SEC) >= 0) {
@@ -761,18 +716,16 @@
 		if ((unsigned) tp->tv_sec < now.tv_sec) {
 			tp->tv_sec = now.tv_sec;
 			tp->tv_nsec = now.tv_nsec;
-		} else {
-			// tp->tv_sec = now.tv_sec + (MAX_JIFFY_OFFSET / HZ);
+		} else
 			/*
 			 * This is a considered response, not exactly in
 			 * line with the standard (in fact it is silent on
-			 * possible overflows).  We assume such a large 
+			 * possible overflows).  We assume such a large
 			 * value is ALMOST always a programming error and
 			 * try not to compound it by setting a really dumb
 			 * value.
 			 */
 			return -EINVAL;
-		}
 	}
 	return 0;
 }
@@ -785,28 +738,27 @@
 {
 	struct k_clock *clock = &posix_clocks[timr->it_clock];
 
-	if (old_setting) {
+	if (old_setting)
 		do_timer_gettime(timr, old_setting);
-	}
 
 	/* disable the timer */
 	timr->it_incr = 0;
-	/* 
+	/*
 	 * careful here.  If smp we could be in the "fire" routine which will
 	 * be spinning as we hold the lock.  But this is ONLY an SMP issue.
 	 */
 #ifdef CONFIG_SMP
-	if (timer_active(timr) && !del_timer(&timr->it_timer)) {
+	if (timer_active(timr) && !del_timer(&timr->it_timer))
 		/*
 		 * It can only be active if on an other cpu.  Since
 		 * we have cleared the interval stuff above, it should
 		 * clear once we release the spin lock.  Of course once
-		 * we do that anything could happen, including the 
-		 * complete melt down of the timer.  So return with 
+		 * we do that anything could happen, including the
+		 * complete melt down of the timer.  So return with
 		 * a "retry" exit status.
 		 */
 		return TIMER_RETRY;
-	}
+
 	set_timer_inactive(timr);
 #else
 	del_timer(&timr->it_timer);
@@ -814,22 +766,21 @@
 	timr->it_requeue_pending = 0;
 	timr->it_overrun_last = 0;
 	timr->it_overrun = -1;
-	/* 
-	 *switch off the timer when it_value is zero 
+	/*
+	 *switch off the timer when it_value is zero
 	 */
-	if ((new_setting->it_value.tv_sec == 0) &&
-	    (new_setting->it_value.tv_nsec == 0)) {
+	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) {
 		timr->it_timer.expires = 0;
 		return 0;
 	}
 
 	if ((flags & TIMER_ABSTIME) &&
-	    (clock->clock_get != do_posix_clock_monotonic_gettime)) {
-	}
+	    (clock->clock_get != do_posix_clock_monotonic_gettime))
+		// FIXME: what is this?
+		;
 	if (adjust_abs_time(clock,
-			    &new_setting->it_value, flags & TIMER_ABSTIME)) {
+			    &new_setting->it_value, flags & TIMER_ABSTIME))
 		return -EINVAL;
-	}
 	tstotimer(new_setting, timr);
 
 	/*
@@ -838,16 +789,16 @@
 	 * We do not even queue SIGEV_NONE timers!
 	 */
 	if (!(timr->it_sigev_notify & SIGEV_NONE)) {
-		if (timr->it_timer.expires == jiffies) {
+		if (timr->it_timer.expires == jiffies)
 			timer_notify_task(timr);
-		} else
+		else
 			add_timer(&timr->it_timer);
 	}
 	return 0;
 }
 
 /* Set a POSIX.1b interval timer */
-asmlinkage int
+asmlinkage long
 sys_timer_settime(timer_t timer_id, int flags,
 		  const struct itimerspec *new_setting,
 		  struct itimerspec *old_setting)
@@ -858,62 +809,54 @@
 	long flag;
 	struct itimerspec *rtn = old_setting ? &old_spec : NULL;
 
-	if (new_setting == NULL) {
+	if (!new_setting)
 		return -EINVAL;
-	}
 
-	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) {
+	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
 		return -EFAULT;
-	}
 
 	if ((!good_timespec(&new_spec.it_interval)) ||
-	    (!good_timespec(&new_spec.it_value))) {
+	    (!good_timespec(&new_spec.it_value)))
 		return -EINVAL;
-	}
-      retry:
+retry:
 	timr = lock_timer(timer_id, &flag);
 	if (!timr)
 		return -EINVAL;
 
-	if (!posix_clocks[timr->it_clock].timer_set) {
+	if (!posix_clocks[timr->it_clock].timer_set)
 		error = do_timer_settime(timr, flags, &new_spec, rtn);
-	} else {
+	else
 		error = posix_clocks[timr->it_clock].timer_set(timr,
 							       flags,
 							       &new_spec, rtn);
-	}
 	unlock_timer(timr, flag);
 	if (error == TIMER_RETRY) {
 		rtn = NULL;	// We already got the old time...
 		goto retry;
 	}
 
-	if (old_setting && !error) {
-		if (copy_to_user(old_setting, &old_spec, sizeof (old_spec))) {
-			error = -EFAULT;
-		}
-	}
+	if (old_setting && !error && copy_to_user(old_setting,
+						  &old_spec, sizeof (old_spec)))
+		error = -EFAULT;
 
 	return error;
 }
 
-static inline int
-do_timer_delete(struct k_itimer *timer)
+static inline int do_timer_delete(struct k_itimer *timer)
 {
 	timer->it_incr = 0;
 #ifdef CONFIG_SMP
 	if (timer_active(timer) &&
-	    !del_timer(&timer->it_timer) && !timer->it_requeue_pending) {
+	    !del_timer(&timer->it_timer) && !timer->it_requeue_pending)
 		/*
 		 * It can only be active if on an other cpu.  Since
 		 * we have cleared the interval stuff above, it should
 		 * clear once we release the spin lock.  Of course once
-		 * we do that anything could happen, including the 
-		 * complete melt down of the timer.  So return with 
+		 * we do that anything could happen, including the
+		 * complete melt down of the timer.  So return with
 		 * a "retry" exit status.
 		 */
 		return TIMER_RETRY;
-	}
 #else
 	del_timer(&timer->it_timer);
 #endif
@@ -921,7 +864,7 @@
 }
 
 /* Delete a POSIX.1b interval timer. */
-asmlinkage int
+asmlinkage long
 sys_timer_delete(timer_t timer_id)
 {
 	struct k_itimer *timer;
@@ -929,9 +872,8 @@
 
 #ifdef CONFIG_SMP
 	int error;
-      retry_delete:
+retry_delete:
 #endif
-
 	timer = lock_timer(timer_id, &flags);
 	if (!timer)
 		return -EINVAL;
@@ -946,13 +888,9 @@
 #else
 	p_timer_del(&posix_clocks[timer->it_clock], timer);
 #endif
-
 	task_lock(timer->it_process);
-
 	list_del(&timer->list);
-
 	task_unlock(timer->it_process);
-
 	/*
 	 * This keeps any tasks waiting on the spin lock from thinking
 	 * they got something (see the lock code above).
@@ -963,20 +901,17 @@
 	return 0;
 }
 /*
- * return  timer owned by the process, used by exit_itimers
+ * return timer owned by the process, used by exit_itimers
  */
-static inline void
-itimer_delete(struct k_itimer *timer)
+static inline void itimer_delete(struct k_itimer *timer)
 {
-	if (sys_timer_delete(timer->it_id)) {
+	if (sys_timer_delete(timer->it_id))
 		BUG();
-	}
 }
 /*
  * This is exported to exit and exec
  */
-void
-exit_itimers(struct task_struct *tsk)
+void exit_itimers(struct task_struct *tsk)
 {
 	struct k_itimer *tmr;
 
@@ -992,18 +927,15 @@
 
 /*
  * And now for the "clock" calls
-
+ *
  * These functions are called both from timer functions (with the timer
  * spin_lock_irq() held and from clock calls with no locking.	They must
  * use the save flags versions of locks.
  */
-static int
-do_posix_gettime(struct k_clock *clock, struct timespec *tp)
+static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
 {
-
-	if (clock->clock_get) {
+	if (clock->clock_get)
 		return clock->clock_get(tp);
-	}
 
 	do_gettimeofday((struct timeval *) tp);
 	tp->tv_nsec *= NSEC_PER_USEC;
@@ -1013,27 +945,24 @@
 /*
  * We do ticks here to avoid the irq lock ( they take sooo long).
  * The seqlock is great here.  Since we a reader, we don't really care
- * if we are interrupted since we don't take lock that will stall us or 
+ * if we are interrupted since we don't take lock that will stall us or
  * any other cpu. Voila, no irq lock is needed.
-
+ *
  * Note also that the while loop assures that the sub_jiff_offset
  * will be less than a jiffie, thus no need to normalize the result.
  * Well, not really, if called with ints off :(
-
- * HELP, this code should make an attempt at resolution beyond the 
+ *
+ * HELP, this code should make an attempt at resolution beyond the
  * jiffie.  Trouble is this is "arch" dependent...
  */
 
-int
-do_posix_clock_monotonic_gettime(struct timespec *tp)
+int do_posix_clock_monotonic_gettime(struct timespec *tp)
 {
 	long sub_sec;
 	u64 jiffies_64_f;
 
 #if (BITS_PER_LONG > 32)
-
 	jiffies_64_f = jiffies_64;
-
 #else
 	unsigned int seq;
 
@@ -1041,75 +970,74 @@
 		seq = read_seqbegin(&xtime_lock);
 		jiffies_64_f = jiffies_64;
 
-	}while(  read_seqretry(&xtime_lock, seq));
-
+	} while (read_seqretry(&xtime_lock, seq));
 #endif
 	tp->tv_sec = div_long_long_rem(jiffies_64_f, HZ, &sub_sec);
-
 	tp->tv_nsec = sub_sec * (NSEC_PER_SEC / HZ);
+
 	return 0;
 }
 
-int
-do_posix_clock_monotonic_settime(struct timespec *tp)
+int do_posix_clock_monotonic_settime(struct timespec *tp)
 {
 	return -EINVAL;
 }
 
-asmlinkage int
+asmlinkage long
 sys_clock_settime(clockid_t which_clock, const struct timespec *tp)
 {
 	struct timespec new_tp;
 
 	if ((unsigned) which_clock >= MAX_CLOCKS ||
-	    !posix_clocks[which_clock].res) return -EINVAL;
+					!posix_clocks[which_clock].res)
+		return -EINVAL;
 	if (copy_from_user(&new_tp, tp, sizeof (*tp)))
 		return -EFAULT;
-	if (posix_clocks[which_clock].clock_set) {
+	if (posix_clocks[which_clock].clock_set)
 		return posix_clocks[which_clock].clock_set(&new_tp);
-	}
+
 	new_tp.tv_nsec /= NSEC_PER_USEC;
 	return do_sys_settimeofday((struct timeval *) &new_tp, NULL);
 }
-asmlinkage int
+
+asmlinkage long
 sys_clock_gettime(clockid_t which_clock, struct timespec *tp)
 {
 	struct timespec rtn_tp;
 	int error = 0;
 
 	if ((unsigned) which_clock >= MAX_CLOCKS ||
-	    !posix_clocks[which_clock].res) return -EINVAL;
+					!posix_clocks[which_clock].res)
+		return -EINVAL;
 
 	error = do_posix_gettime(&posix_clocks[which_clock], &rtn_tp);
 
-	if (!error) {
-		if (copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) {
-			error = -EFAULT;
-		}
-	}
+	if (!error && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
+		error = -EFAULT;
+
 	return error;
 
 }
-asmlinkage int
+
+asmlinkage long
 sys_clock_getres(clockid_t which_clock, struct timespec *tp)
 {
 	struct timespec rtn_tp;
 
 	if ((unsigned) which_clock >= MAX_CLOCKS ||
-	    !posix_clocks[which_clock].res) return -EINVAL;
+					!posix_clocks[which_clock].res)
+		return -EINVAL;
 
 	rtn_tp.tv_sec = 0;
 	rtn_tp.tv_nsec = posix_clocks[which_clock].res;
-	if (tp) {
-		if (copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) {
-			return -EFAULT;
-		}
-	}
+	if (tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
+		return -EFAULT;
+
 	return 0;
 
 }
-static void
-nanosleep_wake_up(unsigned long __data)
+
+static void nanosleep_wake_up(unsigned long __data)
 {
 	struct task_struct *p = (struct task_struct *) __data;
 
@@ -1119,29 +1047,27 @@
 /*
  * The standard says that an absolute nanosleep call MUST wake up at
  * the requested time in spite of clock settings.  Here is what we do:
- * For each nanosleep call that needs it (only absolute and not on 
+ * For each nanosleep call that needs it (only absolute and not on
  * CLOCK_MONOTONIC* (as it can not be set)) we thread a little structure
  * into the "nanosleep_abs_list".  All we need is the task_struct pointer.
  * When ever the clock is set we just wake up all those tasks.	 The rest
  * is done by the while loop in clock_nanosleep().
-
- * On locking, clock_was_set() is called from update_wall_clock which 
- * holds (or has held for it) a write_lock_irq( xtime_lock) and is 
+ *
+ * On locking, clock_was_set() is called from update_wall_clock which
+ * holds (or has held for it) a write_lock_irq( xtime_lock) and is
  * called from the timer bh code.  Thus we need the irq save locks.
  */
 
 static DECLARE_WAIT_QUEUE_HEAD(nanosleep_abs_wqueue);
 
-
-void
-clock_was_set(void)
+void clock_was_set(void)
 {
 	wake_up_all(&nanosleep_abs_wqueue);
 }
 
 long clock_nanosleep_restart(struct restart_block *restart_block);
 
-extern long do_clock_nanosleep(clockid_t which_clock, int flags, 
+extern long do_clock_nanosleep(clockid_t which_clock, int flags,
 			       struct timespec *t);
 
 #ifdef FOLD_NANO_SLEEP_INTO_CLOCK_NANO_SLEEP
@@ -1160,9 +1086,9 @@
 
 	ret = do_clock_nanosleep(CLOCK_REALTIME, 0, &t);
 
-	if (ret == -ERESTART_RESTARTBLOCK && rmtp && 
-	    copy_to_user(rmtp, &t, sizeof (t)))
-			return -EFAULT;
+	if (ret == -ERESTART_RESTARTBLOCK && rmtp &&
+					copy_to_user(rmtp, &t, sizeof (t)))
+		return -EFAULT;
 	return ret;
 }
 #endif				// ! FOLD_NANO_SLEEP_INTO_CLOCK_NANO_SLEEP
@@ -1175,7 +1101,8 @@
 	int ret;
 
 	if ((unsigned) which_clock >= MAX_CLOCKS ||
-	    !posix_clocks[which_clock].res) return -EINVAL;
+					!posix_clocks[which_clock].res)
+		return -EINVAL;
 
 	if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
 		return -EFAULT;
@@ -1185,11 +1112,10 @@
 
 	ret = do_clock_nanosleep(which_clock, flags, &t);
 
-	if ((ret == -ERESTART_RESTARTBLOCK) && rmtp && 
-	    copy_to_user(rmtp, &t, sizeof (t)))
-			return -EFAULT;
+	if ((ret == -ERESTART_RESTARTBLOCK) && rmtp &&
+					copy_to_user(rmtp, &t, sizeof (t)))
+		return -EFAULT;
 	return ret;
-
 }
 
 long
@@ -1228,9 +1154,8 @@
 	}
 
 	if (abs && (posix_clocks[which_clock].clock_get !=
-		    posix_clocks[CLOCK_MONOTONIC].clock_get)) {
+			    posix_clocks[CLOCK_MONOTONIC].clock_get))
 		add_wait_queue(&nanosleep_abs_wqueue, &abs_wqueue);
-	}
 
 	do {
 		t = *tsave;
@@ -1291,8 +1216,8 @@
 	struct timespec t;
 	int ret = do_clock_nanosleep(restart_block->arg0, 0, &t);
 
-	if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 && 
-	    copy_to_user((struct timespec *)(restart_block->arg1), &t, 
+	if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
+	    copy_to_user((struct timespec *)(restart_block->arg1), &t,
 			 sizeof (t)))
 		return -EFAULT;
 	return ret;
diff -urN linux-2.5.65-bk4/kernel/sched.c linux-2.5.65-bk5/kernel/sched.c
--- linux-2.5.65-bk4/kernel/sched.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/kernel/sched.c	Mon Mar 31 12:44:34 2003
@@ -778,7 +778,7 @@
 		spin_unlock(&rq2->lock);
 }
 
-#if CONFIG_NUMA
+#ifdef CONFIG_NUMA
 /*
  * If dest_cpu is allowed for this process, migrate the task to it.
  * This is accomplished by forcing the cpu_allowed mask to only
@@ -1104,7 +1104,7 @@
 #define IDLE_NODE_REBALANCE_TICK (IDLE_REBALANCE_TICK * 5)
 #define BUSY_NODE_REBALANCE_TICK (BUSY_REBALANCE_TICK * 100)
 
-#if CONFIG_NUMA
+#ifdef CONFIG_NUMA
 static void balance_node(runqueue_t *this_rq, int idle, int this_cpu)
 {
 	int node = find_busiest_node(cpu_to_node(this_cpu));
@@ -1121,7 +1121,7 @@
 
 static void rebalance_tick(runqueue_t *this_rq, int idle)
 {
-#if CONFIG_NUMA
+#ifdef CONFIG_NUMA
 	int this_cpu = smp_processor_id();
 #endif
 	unsigned long j = jiffies;
@@ -1135,7 +1135,7 @@
 	 * are not balanced.)
 	 */
 	if (idle) {
-#if CONFIG_NUMA
+#ifdef CONFIG_NUMA
 		if (!(j % IDLE_NODE_REBALANCE_TICK))
 			balance_node(this_rq, idle, this_cpu);
 #endif
@@ -1146,7 +1146,7 @@
 		}
 		return;
 	}
-#if CONFIG_NUMA
+#ifdef CONFIG_NUMA
 	if (!(j % BUSY_NODE_REBALANCE_TICK))
 		balance_node(this_rq, idle, this_cpu);
 #endif
@@ -2268,7 +2268,7 @@
 	local_irq_restore(flags);
 
 	/* Set the preempt count _outside_ the spinlocks! */
-#if CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT
 	idle->thread_info->preempt_count = (idle->lock_depth >= 0);
 #else
 	idle->thread_info->preempt_count = 0;
diff -urN linux-2.5.65-bk4/kernel/sysctl.c linux-2.5.65-bk5/kernel/sysctl.c
--- linux-2.5.65-bk4/kernel/sysctl.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk5/kernel/sysctl.c	Mon Mar 31 12:44:34 2003
@@ -20,6 +20,7 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
diff -urN linux-2.5.65-bk4/kernel/timer.c linux-2.5.65-bk5/kernel/timer.c
--- linux-2.5.65-bk4/kernel/timer.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/kernel/timer.c	Mon Mar 31 12:44:34 2003
@@ -24,6 +24,7 @@
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/notifier.h>
 #include <linux/thread_info.h>
 #include <linux/time.h>
diff -urN linux-2.5.65-bk4/mm/filemap.c linux-2.5.65-bk5/mm/filemap.c
--- linux-2.5.65-bk4/mm/filemap.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/mm/filemap.c	Mon Mar 31 12:44:34 2003
@@ -17,6 +17,7 @@
 #include <linux/aio.h>
 #include <linux/kernel_stat.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
diff -urN linux-2.5.65-bk4/mm/fremap.c linux-2.5.65-bk5/mm/fremap.c
--- linux-2.5.65-bk4/mm/fremap.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/mm/fremap.c	Mon Mar 31 12:44:34 2003
@@ -7,6 +7,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/file.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
diff -urN linux-2.5.65-bk4/mm/highmem.c linux-2.5.65-bk5/mm/highmem.c
--- linux-2.5.65-bk4/mm/highmem.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/mm/highmem.c	Mon Mar 31 12:44:34 2003
@@ -17,6 +17,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/bio.h>
 #include <linux/pagemap.h>
 #include <linux/mempool.h>
diff -urN linux-2.5.65-bk4/mm/page-writeback.c linux-2.5.65-bk5/mm/page-writeback.c
--- linux-2.5.65-bk4/mm/page-writeback.c	Mon Mar 17 13:44:19 2003
+++ linux-2.5.65-bk5/mm/page-writeback.c	Mon Mar 31 12:44:34 2003
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
diff -urN linux-2.5.65-bk4/mm/rmap.c linux-2.5.65-bk5/mm/rmap.c
--- linux-2.5.65-bk4/mm/rmap.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/mm/rmap.c	Mon Mar 31 12:44:34 2003
@@ -22,6 +22,7 @@
  */
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/swap.h>
 #include <linux/swapops.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff -urN linux-2.5.65-bk4/mm/shmem.c linux-2.5.65-bk5/mm/shmem.c
--- linux-2.5.65-bk4/mm/shmem.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/mm/shmem.c	Mon Mar 31 12:44:34 2003
@@ -1882,7 +1882,7 @@
 		goto out2;
 	}
 #ifdef CONFIG_TMPFS
-	devfs_mk_dir(NULL, "shm", NULL);
+	devfs_mk_dir("shm");
 #endif
 	shm_mnt = kern_mount(&tmpfs_fs_type);
 	if (IS_ERR(shm_mnt)) {
diff -urN linux-2.5.65-bk4/net/bridge/netfilter/ebtable_broute.c linux-2.5.65-bk5/net/bridge/netfilter/ebtable_broute.c
--- linux-2.5.65-bk4/net/bridge/netfilter/ebtable_broute.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk5/net/bridge/netfilter/ebtable_broute.c	Mon Mar 31 12:44:34 2003
@@ -49,6 +49,7 @@
 	.valid_hooks	= 1 << NF_BR_BROUTING,
 	.lock		= RW_LOCK_UNLOCKED,
 	.check		= check,
+	.me		= THIS_MODULE,
 };
 
 static int ebt_broute(struct sk_buff **pskb)
diff -urN linux-2.5.65-bk4/net/bridge/netfilter/ebtable_filter.c linux-2.5.65-bk5/net/bridge/netfilter/ebtable_filter.c
--- linux-2.5.65-bk4/net/bridge/netfilter/ebtable_filter.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk5/net/bridge/netfilter/ebtable_filter.c	Mon Mar 31 12:44:34 2003
@@ -57,6 +57,7 @@
 	.valid_hooks	= FILTER_VALID_HOOKS, 
 	.lock		= RW_LOCK_UNLOCKED,
 	.check		= check,
+	.me		= THIS_MODULE,
 };
 
 static unsigned int
diff -urN linux-2.5.65-bk4/net/bridge/netfilter/ebtable_nat.c linux-2.5.65-bk5/net/bridge/netfilter/ebtable_nat.c
--- linux-2.5.65-bk4/net/bridge/netfilter/ebtable_nat.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk5/net/bridge/netfilter/ebtable_nat.c	Mon Mar 31 12:44:34 2003
@@ -56,6 +56,7 @@
 	.valid_hooks	= NAT_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
 	.check		= check,
+	.me		= THIS_MODULE,
 };
 
 static unsigned int
diff -urN linux-2.5.65-bk4/net/bridge/netfilter/ebtables.c linux-2.5.65-bk5/net/bridge/netfilter/ebtables.c
--- linux-2.5.65-bk4/net/bridge/netfilter/ebtables.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk5/net/bridge/netfilter/ebtables.c	Mon Mar 31 12:44:34 2003
@@ -969,8 +969,10 @@
 		goto free_counterstmp;
 
 	t = find_table_lock(tmp.name, &ret, &ebt_mutex);
-	if (!t)
+	if (!t) {
+		ret = -ENOENT;
 		goto free_iterate;
+	}
 
 	/* the table doesn't like it */
 	if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
@@ -984,6 +986,12 @@
 
 	/* we have the mutex lock, so no danger in reading this pointer */
 	table = t->private;
+	/* make sure the table can only be rmmod'ed if it contains no rules */
+	if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
+		ret = -ENOENT;
+		goto free_unlock;
+	} else if (table->nentries && !newinfo->nentries)
+		module_put(t->me);
 	/* we need an atomic snapshot of the counters */
 	write_lock_bh(&t->lock);
 	if (tmp.num_counters)
@@ -1168,6 +1176,11 @@
 		goto free_unlock;
 	}
 
+	/* Hold a reference count if the chains aren't empty */
+	if (newinfo->nentries && !try_module_get(table->me)) {
+		ret = -ENOENT;
+		goto free_unlock;
+	}
 	list_prepend(&ebt_tables, table);
 	up(&ebt_mutex);
 	return 0;
@@ -1196,8 +1209,6 @@
 	down(&ebt_mutex);
 	LIST_DELETE(&ebt_tables, table);
 	up(&ebt_mutex);
-	EBT_ENTRY_ITERATE(table->private->entries,
-	   table->private->entries_size, ebt_cleanup_entry, NULL);
 	if (table->private->entries)
 		vfree(table->private->entries);
 	if (table->private->chainstack) {
diff -urN linux-2.5.65-bk4/net/compat.c linux-2.5.65-bk5/net/compat.c
--- linux-2.5.65-bk4/net/compat.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/compat.c	Mon Mar 31 12:44:34 2003
@@ -25,15 +25,10 @@
 #include <net/scm.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <net/compat_socket.h>
+#include <net/compat.h>
 
-#define A(__x)		((unsigned long)(__x))
 #define AA(__x)		((unsigned long)(__x))
 
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				       void * optval, int *optlen);
-
-
 static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
 					  struct compat_iovec *uiov32,
 					  int niov)
@@ -41,7 +36,8 @@
 	int tot_len = 0;
 
 	while(niov > 0) {
-		u32 len, buf;
+		compat_uptr_t buf;
+		compat_size_t len;
 
 		if(get_user(len, &uiov32->iov_len) ||
 		   get_user(buf, &uiov32->iov_base)) {
@@ -49,7 +45,7 @@
 			break;
 		}
 		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
+		kiov->iov_base = compat_ptr(buf);
 		kiov->iov_len = (__kernel_size_t) len;
 		uiov32++;
 		kiov++;
@@ -58,27 +54,23 @@
 	return tot_len;
 }
 
-int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *umsg)
+int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr *umsg)
 {
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
+	compat_uptr_t tmp1, tmp2, tmp3;
 
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
+	if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
+	    __get_user(tmp1, &umsg->msg_name) ||
+	    __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
+	    __get_user(tmp2, &umsg->msg_iov) ||
+	    __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) ||
+	    __get_user(tmp3, &umsg->msg_control) ||
+	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
+	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
+		return -EFAULT;
+	kmsg->msg_name = compat_ptr(tmp1);
+	kmsg->msg_iov = compat_ptr(tmp2);
+	kmsg->msg_control = compat_ptr(tmp3);
+	return 0;
 }
 
 /* I've named the args so it is easy to tell whose space the pointers are in. */
@@ -117,6 +109,34 @@
 	return tot_len;
 }
 
+/* Bleech... */
+#define CMSG_COMPAT_ALIGN(len)	ALIGN((len), sizeof(s32))
+
+#define CMSG_COMPAT_DATA(cmsg)				\
+	((void *)((char *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))))
+#define CMSG_COMPAT_SPACE(len)				\
+	(CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len))
+#define CMSG_COMPAT_LEN(len)				\
+	(CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len))
+
+#define CMSG_COMPAT_FIRSTHDR(msg)			\
+	(((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ?	\
+	 (struct compat_cmsghdr *)((msg)->msg_control) :		\
+	 (struct compat_cmsghdr *)NULL)
+
+static inline struct compat_cmsghdr *cmsg_compat_nxthdr(struct msghdr *msg,
+		struct compat_cmsghdr *cmsg, int cmsg_len)
+{
+	struct compat_cmsghdr *ptr;
+
+	ptr = (struct compat_cmsghdr *)(((unsigned char *)cmsg) +
+			CMSG_COMPAT_ALIGN(cmsg_len));
+	if ((unsigned long)((char *)(ptr + 1) - (char *)msg->msg_control) >
+			msg->msg_controllen)
+		return NULL;
+	return ptr;
+}
+
 /* There is a lot of hair here because the alignment rules (and
  * thus placement) of cmsg headers and length are different for
  * 32-bit apps.  -DaveM
@@ -147,7 +167,7 @@
 		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
 		       CMSG_ALIGN(sizeof(struct cmsghdr)));
 		kcmlen += tmp;
-		ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen);
+		ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
 	}
 	if(kcmlen == 0)
 		return -EINVAL;
@@ -181,7 +201,7 @@
 
 		/* Advance. */
 		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen);
+		ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
 	}
 
 	/* Ok, looks like we made it.  Hook it up and return success. */
@@ -304,7 +324,7 @@
  *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
  *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
  */
-void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+static void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
 {
 	unsigned char *workbuf, *wp;
 	unsigned long bufsz, space_avail;
@@ -365,112 +385,133 @@
 	kmsg->msg_control = (void *) orig_cmsg_uptr;
 }
 
+int put_compat_msg_controllen(struct msghdr *msg_sys,
+		struct compat_msghdr *msg_compat, unsigned long cmsg_ptr)
+{
+	unsigned long ucmsg_ptr;
+	compat_size_t uclen;
+
+	if ((unsigned long)msg_sys->msg_control != cmsg_ptr)
+		cmsg_compat_recvmsg_fixup(msg_sys, cmsg_ptr);
+	ucmsg_ptr = ((unsigned long)msg_sys->msg_control);
+	uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
+	return __put_user(uclen, &msg_compat->msg_controllen);
+}
+
 extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
-				      char *optval, int optlen);
+				     char *optval, int optlen);
+
+/*
+ * For now, we assume that the compatibility and native version
+ * of struct ipt_entry are the same - sfr.  FIXME
+ */
+struct compat_ipt_replace {
+	char			name[IPT_TABLE_MAXNAMELEN];
+	u32			valid_hooks;
+	u32			num_entries;
+	u32			size;
+	u32			hook_entry[NF_IP_NUMHOOKS];
+	u32			underflow[NF_IP_NUMHOOKS];
+	u32			num_counters;
+	compat_uptr_t		counters;	/* struct ipt_counters * */
+	struct ipt_entry	entries[0];
+};
 
 static int do_netfilter_replace(int fd, int level, int optname,
 				char *optval, int optlen)
 {
-	struct ipt_replace32 {
-		char name[IPT_TABLE_MAXNAMELEN];
-		__u32 valid_hooks;
-		__u32 num_entries;
-		__u32 size;
-		__u32 hook_entry[NF_IP_NUMHOOKS];
-		__u32 underflow[NF_IP_NUMHOOKS];
-		__u32 num_counters;
-		__u32 counters;
-		struct ipt_entry entries[0];
-	} *repl32 = (struct ipt_replace32 *)optval;
+	struct compat_ipt_replace *urepl = (struct compat_ipt_replace *)optval;
 	struct ipt_replace *krepl;
-	struct ipt_counters *counters32;
-	__u32 origsize;
-	unsigned int kreplsize, kcountersize;
+	u32 origsize;
+	unsigned int kreplsize;
 	mm_segment_t old_fs;
 	int ret;
+	int i;
+	compat_uptr_t ucntrs;
 
-	if (optlen < sizeof(repl32))
-		return -EINVAL;
-
-	if (copy_from_user(&origsize,
-			&repl32->size,
-			sizeof(origsize)))
+	if (get_user(origsize, &urepl->size))
 		return -EFAULT;
 
-	kreplsize = sizeof(*krepl) + origsize;
-	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
-
 	/* Hack: Causes ipchains to give correct error msg --RR */
-	if (optlen != kreplsize)
+	if (optlen != sizeof(*urepl) + origsize)
 		return -ENOPROTOOPT;
 
+	/* XXX Assumes that size of ipt_entry is the same both in
+	 *     native and compat environments.
+	 */
+	kreplsize = sizeof(*krepl) + origsize;
 	krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
 	if (krepl == NULL)
 		return -ENOMEM;
 
-	if (copy_from_user(krepl, optval, kreplsize)) {
-		kfree(krepl);
-		return -EFAULT;
+	ret = -EFAULT;
+	krepl->size = origsize;
+	if (!access_ok(VERIFY_READ, urepl, optlen) ||
+	    __copy_from_user(krepl->name, urepl->name, sizeof(urepl->name)) ||
+	    __get_user(krepl->valid_hooks, &urepl->valid_hooks) ||
+	    __get_user(krepl->num_entries, &urepl->num_entries) ||
+	    __get_user(krepl->num_counters, &urepl->num_counters) ||
+	    __get_user(ucntrs, &urepl->counters) ||
+	    __copy_from_user(krepl->entries, &urepl->entries, origsize))
+		goto out_free;
+	for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+		if (__get_user(krepl->hook_entry[i], &urepl->hook_entry[i]) ||
+		    __get_user(krepl->underflow[i], &urepl->underflow[i]))
+			goto out_free;
 	}
 
-	counters32 = (struct ipt_counters *)AA(
-		((struct ipt_replace32 *)krepl)->counters);
-
-	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
-	krepl->counters = (struct ipt_counters *)kmalloc(
-					kcountersize, GFP_KERNEL);
-	if (krepl->counters == NULL) {
-		kfree(krepl);
-		return -ENOMEM;
-	}
+	/*
+	 * Since struct ipt_counters just contains two u_int64_t members
+	 * we can just do the access_ok check here and pass the (converted)
+	 * pointer into the standard syscall.  We hope that the pointer is
+	 * not misaligned ...
+	 */
+	krepl->counters = compat_ptr(ucntrs);
+	if (!access_ok(VERIFY_WRITE, krepl->counters,
+			krepl->num_counters * sizeof(struct ipt_counters)))
+		goto out_free;
 
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)krepl, kreplsize);
+	ret = sys_setsockopt(fd, level, optname, (char *)krepl, kreplsize);
 	set_fs(old_fs);
 
-	if (ret == 0 &&
-		copy_to_user(counters32, krepl->counters, kcountersize))
-			ret = -EFAULT;
-
-	kfree(krepl->counters);
+out_free:
 	kfree(krepl);
-
 	return ret;
 }
 
+/*
+ * A struct sock_filter is architecture independent.
+ */
+struct compat_sock_fprog {
+	u16		len;
+	compat_uptr_t	filter;		/* struct sock_filter * */
+};
+
 static int do_set_attach_filter(int fd, int level, int optname,
 				char *optval, int optlen)
 {
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
+	struct compat_sock_fprog *fprog32 = (struct compat_sock_fprog *)optval;
 	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
 	mm_segment_t old_fs;
-	__u32 uptr;
+	compat_uptr_t uptr;
 	int ret;
 
-	if (get_user(kfprog.len, &fprog32->len) ||
+	if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) ||
+	    __get_user(kfprog.len, &fprog32->len) ||
 	    __get_user(uptr, &fprog32->filter))
 		return -EFAULT;
 
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
+	kfprog.filter = compat_ptr(uptr);
+	/*
+	 * Since struct sock_filter is architecure independent,
+	 * we can just do the access_ok check and pass the
+	 * same pointer to the real syscall.
+	 */
+	if (!access_ok(VERIFY_READ, kfprog.filter,
+			kfprog.len * sizeof(struct sock_filter)))
 		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
 
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
@@ -478,8 +519,6 @@
 			     (char *)&kfprog, sizeof(kfprog));
 	set_fs(old_fs);
 
-	kfree(kfilter);
-
 	return ret;
 }
 
@@ -490,10 +529,11 @@
 	mm_segment_t old_fs;
 	int ret, i;
 
+	if (optlen < sizeof(kfilter))
+		return -EINVAL;
 	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
 		return -EFAULT;
 
-
 	for (i = 0; i < 8; i += 2) {
 		u32 tmp = kfilter.data[i];
 
@@ -519,7 +559,8 @@
 
 	if (optlen < sizeof(*up))
 		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    __get_user(ktime.tv_sec, &up->tv_sec) ||
 	    __get_user(ktime.tv_usec, &up->tv_usec))
 		return -EFAULT;
 	old_fs = get_fs();
@@ -548,7 +589,11 @@
 	return sys_setsockopt(fd, level, optname, optval, optlen);
 }
 
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
+extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
+				       void * optval, int *optlen);
+
+static int do_get_sock_timeout(int fd, int level, int optname, char *optval,
+		int *optlen)
 {
 	struct compat_timeval *up = (struct compat_timeval *) optval;
 	struct timeval ktime;
@@ -567,7 +612,8 @@
 
 	if (!err) {
 		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
+		    !access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+		    __put_user(ktime.tv_sec, &up->tv_sec) ||
 		    __put_user(ktime.tv_usec, &up->tv_usec))
 			err = -EFAULT;
 	}
@@ -589,27 +635,21 @@
 				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
 #undef AL
 
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
-				  int addrlen);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen); 
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
-				   unsigned flags, u32 addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
-				     unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol,
-				     int usockvec[2]);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_listen(int fd, int backlog);
-
+extern asmlinkage long sys_bind(int, struct sockaddr *, int);
+extern asmlinkage long sys_connect(int, struct sockaddr *, int);
+extern asmlinkage long sys_accept(int, struct sockaddr *, int *); 
+extern asmlinkage long sys_getsockname(int, struct sockaddr *, int *);
+extern asmlinkage long sys_getpeername(int, struct sockaddr *, int *);
+extern asmlinkage long sys_send(int, void *, size_t, unsigned);
+extern asmlinkage long sys_sendto(int, void *, size_t, unsigned,
+		struct sockaddr *, int);
+extern asmlinkage long sys_recv(int, void *, size_t, unsigned);
+extern asmlinkage long sys_recvfrom(int, void *, size_t, unsigned,
+		struct sockaddr *, int *);
+extern asmlinkage long sys_socket(int, int, int);
+extern asmlinkage long sys_socketpair(int, int, int, int [2]);
+extern asmlinkage long sys_shutdown(int, int);
+extern asmlinkage long sys_listen(int, int);
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr *msg, unsigned flags)
 {
@@ -639,58 +679,54 @@
 		ret = sys_socket(a0, a1, a[2]);
 		break;
 	case SYS_BIND:
-		ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+		ret = sys_bind(a0, compat_ptr(a1), a[2]);
 		break;
 	case SYS_CONNECT:
-		ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+		ret = sys_connect(a0, compat_ptr(a1), a[2]);
 		break;
 	case SYS_LISTEN:
 		ret = sys_listen(a0, a1);
 		break;
 	case SYS_ACCEPT:
-		ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
+		ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
 		break;
 	case SYS_GETSOCKNAME:
-		ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
-				       (int *)A(a[2]));
+		ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
 		break;
 	case SYS_GETPEERNAME:
-		ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
-				       (int *)A(a[2]));
+		ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
 		break;
 	case SYS_SOCKETPAIR:
-		ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+		ret = sys_socketpair(a0, a1, a[2], compat_ptr(a[3]));
 		break;
 	case SYS_SEND:
-		ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+		ret = sys_send(a0, compat_ptr(a1), a[2], a[3]);
 		break;
 	case SYS_SENDTO:
-		ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
+		ret = sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]);
 		break;
 	case SYS_RECV:
-		ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+		ret = sys_recv(a0, compat_ptr(a1), a[2], a[3]);
 		break;
 	case SYS_RECVFROM:
-		ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
+		ret = sys_recvfrom(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), compat_ptr(a[5]));
 		break;
 	case SYS_SHUTDOWN:
 		ret = sys_shutdown(a0,a1);
 		break;
 	case SYS_SETSOCKOPT:
-		ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
-				      a[4]);
+		ret = compat_sys_setsockopt(a0, a1, a[2],
+				compat_ptr(a[3]), a[4]);
 		break;
 	case SYS_GETSOCKOPT:
-		ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3],
-					    (int *)(u64)a[4]);
+		ret = compat_sys_getsockopt(a0, a1, a[2],
+				compat_ptr(a[3]), compat_ptr(a[4]));
 		break;
 	case SYS_SENDMSG:
-		ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1),
-				         a[2]);
+		ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
 		break;
 	case SYS_RECVMSG:
-		ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1),
-				         a[2]);
+		ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
 		break;
 	default:
 		ret = -EINVAL;
diff -urN linux-2.5.65-bk4/net/core/scm.c linux-2.5.65-bk5/net/core/scm.c
--- linux-2.5.65-bk4/net/core/scm.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/net/core/scm.c	Mon Mar 31 12:44:34 2003
@@ -30,6 +30,7 @@
 #include <net/protocol.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
+#include <net/compat.h>
 #include <net/scm.h>
 
 
diff -urN linux-2.5.65-bk4/net/ipv4/Makefile linux-2.5.65-bk5/net/ipv4/Makefile
--- linux-2.5.65-bk4/net/ipv4/Makefile	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk5/net/ipv4/Makefile	Mon Mar 31 12:44:34 2003
@@ -22,4 +22,4 @@
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 obj-$(CONFIG_XFRM_USER) += xfrm_user.o
 
-obj-y += xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o
+obj-y += xfrm_policy.o xfrm4_policy.o xfrm_state.o xfrm4_state.o xfrm_input.o xfrm4_input.o xfrm_algo.o
diff -urN linux-2.5.65-bk4/net/ipv4/ah.c linux-2.5.65-bk5/net/ipv4/ah.c
--- linux-2.5.65-bk4/net/ipv4/ah.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/ah.c	Mon Mar 31 12:44:34 2003
@@ -92,8 +92,8 @@
 		top_iph->ttl = 0;
 		top_iph->protocol = IPPROTO_AH;
 		top_iph->check = 0;
-		top_iph->saddr = x->props.saddr.xfrm4_addr;
-		top_iph->daddr = x->id.daddr.xfrm4_addr;
+		top_iph->saddr = x->props.saddr.a4;
+		top_iph->daddr = x->id.daddr.a4;
 		ah = (struct ip_auth_hdr*)(top_iph+1);
 		ah->nexthdr = IPPROTO_IPIP;
 	} else {
@@ -232,7 +232,7 @@
 	    skb->h.icmph->code != ICMP_FRAG_NEEDED)
 		return;
 
-	x = xfrm4_state_lookup(iph->daddr, ah->spi, IPPROTO_AH);
+	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/%08x\n",
@@ -338,13 +338,13 @@
 static int __init ah4_init(void)
 {
 	SET_MODULE_OWNER(&ah_type);
-	if (xfrm_register_type(&ah_type) < 0) {
+	if (xfrm_register_type(&ah_type, AF_INET) < 0) {
 		printk(KERN_INFO "ip ah init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
 	if (inet_add_protocol(&ah4_protocol, IPPROTO_AH) < 0) {
 		printk(KERN_INFO "ip ah init: can't add protocol\n");
-		xfrm_unregister_type(&ah_type);
+		xfrm_unregister_type(&ah_type, AF_INET);
 		return -EAGAIN;
 	}
 	return 0;
@@ -354,7 +354,7 @@
 {
 	if (inet_del_protocol(&ah4_protocol, IPPROTO_AH) < 0)
 		printk(KERN_INFO "ip ah close: can't remove protocol\n");
-	if (xfrm_unregister_type(&ah_type) < 0)
+	if (xfrm_unregister_type(&ah_type, AF_INET) < 0)
 		printk(KERN_INFO "ip ah close: can't remove xfrm type\n");
 }
 
diff -urN linux-2.5.65-bk4/net/ipv4/esp.c linux-2.5.65-bk5/net/ipv4/esp.c
--- linux-2.5.65-bk4/net/ipv4/esp.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/esp.c	Mon Mar 31 12:44:34 2003
@@ -91,8 +91,8 @@
 		top_iph->ttl = iph->ttl;	/* TTL disclosed */
 		top_iph->protocol = IPPROTO_ESP;
 		top_iph->check = 0;
-		top_iph->saddr = x->props.saddr.xfrm4_addr;
-		top_iph->daddr = x->id.daddr.xfrm4_addr;
+		top_iph->saddr = x->props.saddr.a4;
+		top_iph->daddr = x->id.daddr.a4;
 		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 	} else {
 		esph = (struct ip_esp_hdr*)skb_push(skb, x->props.header_len);
@@ -276,7 +276,7 @@
 	    skb->h.icmph->code != ICMP_FRAG_NEEDED)
 		return;
 
-	x = xfrm4_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP);
+	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/%08x\n",
@@ -405,13 +405,13 @@
 int __init esp4_init(void)
 {
 	SET_MODULE_OWNER(&esp_type);
-	if (xfrm_register_type(&esp_type) < 0) {
+	if (xfrm_register_type(&esp_type, AF_INET) < 0) {
 		printk(KERN_INFO "ip esp init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
 	if (inet_add_protocol(&esp4_protocol, IPPROTO_ESP) < 0) {
 		printk(KERN_INFO "ip esp init: can't add protocol\n");
-		xfrm_unregister_type(&esp_type);
+		xfrm_unregister_type(&esp_type, AF_INET);
 		return -EAGAIN;
 	}
 	return 0;
@@ -421,7 +421,7 @@
 {
 	if (inet_del_protocol(&esp4_protocol, IPPROTO_ESP) < 0)
 		printk(KERN_INFO "ip esp close: can't remove protocol\n");
-	if (xfrm_unregister_type(&esp_type) < 0)
+	if (xfrm_unregister_type(&esp_type, AF_INET) < 0)
 		printk(KERN_INFO "ip esp close: can't remove xfrm type\n");
 }
 
diff -urN linux-2.5.65-bk4/net/ipv4/ip_forward.c linux-2.5.65-bk5/net/ipv4/ip_forward.c
--- linux-2.5.65-bk4/net/ipv4/ip_forward.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/ip_forward.c	Mon Mar 31 12:44:34 2003
@@ -60,7 +60,7 @@
 	struct rtable *rt;	/* Route we use */
 	struct ip_options * opt	= &(IPCB(skb)->opt);
 
-	if (!xfrm_policy_check(NULL, XFRM_POLICY_FWD, skb))
+	if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))
 		goto drop;
 
 	if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
@@ -82,7 +82,7 @@
 	if (iph->ttl <= 1)
                 goto too_many_hops;
 
-	if (!xfrm_route_forward(skb))
+	if (!xfrm4_route_forward(skb))
 		goto drop;
 
 	iph = skb->nh.iph;
diff -urN linux-2.5.65-bk4/net/ipv4/ip_input.c linux-2.5.65-bk5/net/ipv4/ip_input.c
--- linux-2.5.65-bk4/net/ipv4/ip_input.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk5/net/ipv4/ip_input.c	Mon Mar 31 12:44:34 2003
@@ -236,7 +236,7 @@
 			int ret;
 
 			if (!ipprot->no_policy &&
-			    !xfrm_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 				kfree_skb(skb);
 				return 0;
 			}
@@ -248,7 +248,7 @@
 			IP_INC_STATS_BH(IpInDelivers);
 		} else {
 			if (!raw_sk) {
-				if (xfrm_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+				if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 					IP_INC_STATS_BH(IpInUnknownProtos);
 					icmp_send(skb, ICMP_DEST_UNREACH,
 						  ICMP_PROT_UNREACH, 0);
diff -urN linux-2.5.65-bk4/net/ipv4/raw.c linux-2.5.65-bk5/net/ipv4/raw.c
--- linux-2.5.65-bk4/net/ipv4/raw.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/raw.c	Mon Mar 31 12:44:34 2003
@@ -251,7 +251,7 @@
 
 int raw_rcv(struct sock *sk, struct sk_buff *skb)
 {
-	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb)) {
+	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
 		kfree_skb(skb);
 		return NET_RX_DROP;
 	}
diff -urN linux-2.5.65-bk4/net/ipv4/route.c linux-2.5.65-bk5/net/ipv4/route.c
--- linux-2.5.65-bk4/net/ipv4/route.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/route.c	Mon Mar 31 12:44:34 2003
@@ -2600,13 +2600,6 @@
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_CLS_ROUTE */
 
-int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
-{
-        int err = 0;
-        err = __ip_route_output_key((struct rtable**)dst, fl);
-        return err;
-}
-
 int __init ip_rt_init(void)
 {
 	int i, order, goal, rc = 0;
@@ -2688,7 +2681,6 @@
 					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
-	xfrm_dst_lookup_register(xfrm_dst_lookup, AF_INET);
 #ifdef CONFIG_PROC_FS
 	if (rt_cache_proc_init())
 		goto out_enomem;
@@ -2698,6 +2690,7 @@
 #endif
 #endif
 	xfrm_init();
+	xfrm4_init();
 out:
 	return rc;
 out_enomem:
diff -urN linux-2.5.65-bk4/net/ipv4/tcp_ipv4.c linux-2.5.65-bk5/net/ipv4/tcp_ipv4.c
--- linux-2.5.65-bk4/net/ipv4/tcp_ipv4.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/tcp_ipv4.c	Mon Mar 31 12:44:34 2003
@@ -1798,7 +1798,7 @@
 	if (sk->state == TCP_TIME_WAIT)
 		goto do_time_wait;
 
-	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb))
+	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
 		goto discard_and_relse;
 
 	if (sk_filter(sk, skb, 0))
@@ -1820,7 +1820,7 @@
 	return ret;
 
 no_tcp_socket:
-	if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb))
+	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto discard_it;
 
 	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
@@ -1840,7 +1840,7 @@
 	goto discard_it;
 
 do_time_wait:
-	if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb))
+	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto discard_and_relse;
 
 	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
diff -urN linux-2.5.65-bk4/net/ipv4/udp.c linux-2.5.65-bk5/net/ipv4/udp.c
--- linux-2.5.65-bk4/net/ipv4/udp.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk5/net/ipv4/udp.c	Mon Mar 31 12:44:34 2003
@@ -946,7 +946,7 @@
 	/*
 	 *	Charge it to the socket, dropping if the queue is full.
 	 */
-	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb)) {
+	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
 		kfree_skb(skb);
 		return -1;
 	}
@@ -1077,7 +1077,7 @@
 		return 0;
 	}
 
-	if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb))
+	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto drop;
 
 	/* No socket. Drop packet silently, if checksum is wrong */
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm4_input.c linux-2.5.65-bk5/net/ipv4/xfrm4_input.c
--- linux-2.5.65-bk4/net/ipv4/xfrm4_input.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/net/ipv4/xfrm4_input.c	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,129 @@
+/*
+ * xfrm4_input.c
+ *
+ * Changes:
+ *	YOSHIFUJI Hideaki @USAGI
+ *		Split up af-specific portion
+ * 	
+ */
+
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+static kmem_cache_t *secpath_cachep;
+
+int xfrm4_rcv(struct sk_buff *skb)
+{
+	int err;
+	u32 spi, seq;
+	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
+	struct xfrm_state *x;
+	int xfrm_nr = 0;
+	int decaps = 0;
+
+	if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
+		goto drop;
+
+	do {
+		struct iphdr *iph = skb->nh.iph;
+
+		if (xfrm_nr == XFRM_MAX_DEPTH)
+			goto drop;
+
+		x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, iph->protocol, AF_INET);
+		if (x == NULL)
+			goto drop;
+
+		spin_lock(&x->lock);
+		if (unlikely(x->km.state != XFRM_STATE_VALID))
+			goto drop_unlock;
+
+		if (x->props.replay_window && xfrm_replay_check(x, seq))
+			goto drop_unlock;
+
+		if (x->type->input(x, skb))
+			goto drop_unlock;
+
+		if (x->props.replay_window)
+			xfrm_replay_advance(x, seq);
+
+		x->curlft.bytes += skb->len;
+		x->curlft.packets++;
+
+		spin_unlock(&x->lock);
+
+		xfrm_vec[xfrm_nr++] = x;
+
+		iph = skb->nh.iph;
+
+		if (x->props.mode) {
+			if (iph->protocol != IPPROTO_IPIP)
+				goto drop;
+			skb->nh.raw = skb->data;
+			iph = skb->nh.iph;
+			memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+			decaps = 1;
+			break;
+		}
+
+		if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) < 0)
+			goto drop;
+	} while (!err);
+
+	/* Allocate new secpath or COW existing one. */
+
+	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+		kmem_cache_t *pool = skb->sp ? skb->sp->pool : secpath_cachep;
+		struct sec_path *sp;
+		sp = kmem_cache_alloc(pool, SLAB_ATOMIC);
+		if (!sp)
+			goto drop;
+		if (skb->sp) {
+			memcpy(sp, skb->sp, sizeof(struct sec_path));
+			secpath_put(skb->sp);
+		} else {
+			sp->pool = pool;
+			sp->len = 0;
+		}
+		atomic_set(&sp->refcnt, 1);
+		skb->sp = sp;
+	}
+	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
+		goto drop;
+
+	memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*));
+	skb->sp->len += xfrm_nr;
+
+	if (decaps) {
+		if (!(skb->dev->flags&IFF_LOOPBACK)) {
+			dst_release(skb->dst);
+			skb->dst = NULL;
+		}
+		netif_rx(skb);
+		return 0;
+	} else {
+		return -skb->nh.iph->protocol;
+	}
+
+drop_unlock:
+	spin_unlock(&x->lock);
+	xfrm_state_put(x);
+drop:
+	while (--xfrm_nr >= 0)
+		xfrm_state_put(xfrm_vec[xfrm_nr]);
+	kfree_skb(skb);
+	return 0;
+}
+
+
+void __init xfrm4_input_init(void)
+{
+	secpath_cachep = kmem_cache_create("secpath4_cache",
+					   sizeof(struct sec_path),
+					   0, SLAB_HWCACHE_ALIGN,
+					   NULL, NULL);
+
+	if (!secpath_cachep)
+		panic("IP: failed to allocate secpath4_cache\n");
+}
+
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm4_policy.c linux-2.5.65-bk5/net/ipv4/xfrm4_policy.c
--- linux-2.5.65-bk4/net/ipv4/xfrm4_policy.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/net/ipv4/xfrm4_policy.c	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,277 @@
+/* 
+ * xfrm4_policy.c
+ *
+ * Changes:
+ *	Kazunori MIYAZAWA @USAGI
+ * 	YOSHIFUJI Hideaki @USAGI
+ *		Split up af-specific portion
+ * 	
+ */
+
+#include <linux/config.h>
+#include <net/xfrm.h>
+#include <net/ip.h>
+
+extern struct dst_ops xfrm4_dst_ops;
+extern struct xfrm_policy_afinfo xfrm4_policy_afinfo;
+
+static struct xfrm_type_map xfrm4_type_map = { .lock = RW_LOCK_UNLOCKED };
+
+static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+	return __ip_route_output_key((struct rtable**)dst, fl);
+}
+
+/* Check that the bundle accepts the flow and its components are
+ * still valid.
+ */
+
+static int __xfrm4_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
+{
+	do {
+		if (xdst->u.dst.ops != &xfrm4_dst_ops)
+			return 1;
+
+		if (!xfrm_selector_match(&xdst->u.dst.xfrm->sel, fl, AF_INET))
+			return 0;
+		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
+		    xdst->u.dst.path->obsolete > 0)
+			return 0;
+		xdst = (struct xfrm_dst*)xdst->u.dst.child;
+	} while (xdst);
+	return 0;
+}
+
+static struct dst_entry *
+__xfrm4_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy)
+{
+	struct dst_entry *dst;
+
+	if (!fl->fl4_src)
+		fl->fl4_src = rt->rt_src;
+	if (!fl->fl4_dst)
+		fl->fl4_dst = rt->rt_dst;
+	read_lock_bh(&policy->lock);
+	for (dst = policy->bundles; dst; dst = dst->next) {
+		struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
+		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
+	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+		    __xfrm4_bundle_ok(xdst, fl)) {
+			dst_clone(dst);
+			break;
+		}
+	}
+	read_unlock_bh(&policy->lock);
+	return dst;
+}
+
+/* Allocate chain of dst_entry's, attach known xfrm's, calculate
+ * all the metrics... Shortly, bundle a bundle.
+ */
+
+static int
+__xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
+		      struct flowi *fl, struct dst_entry **dst_p)
+{
+	struct dst_entry *dst, *dst_prev;
+	struct rtable *rt0 = (struct rtable*)(*dst_p);
+	struct rtable *rt = rt0;
+	u32 remote = fl->fl4_dst;
+	u32 local  = fl->fl4_src;
+	int i;
+	int err;
+	int header_len = 0;
+	int trailer_len = 0;
+
+	dst = dst_prev = NULL;
+
+	for (i = 0; i < nx; i++) {
+		struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
+
+		if (unlikely(dst1 == NULL)) {
+			err = -ENOBUFS;
+			goto error;
+		}
+
+		dst1->xfrm = xfrm[i];
+		if (!dst)
+			dst = dst1;
+		else {
+			dst_prev->child = dst1;
+			dst1->flags |= DST_NOHASH;
+			dst_clone(dst1);
+		}
+		dst_prev = dst1;
+		if (xfrm[i]->props.mode) {
+			remote = xfrm[i]->id.daddr.a4;
+			local  = xfrm[i]->props.saddr.a4;
+		}
+		header_len += xfrm[i]->props.header_len;
+		trailer_len += xfrm[i]->props.trailer_len;
+	}
+
+	if (remote != fl->fl4_dst) {
+		struct flowi fl_tunnel = { .nl_u = { .ip4_u =
+						     { .daddr = remote,
+						       .saddr = local }
+					           }
+				         };
+		err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET);
+		if (err)
+			goto error;
+	} else {
+		dst_hold(&rt->u.dst);
+	}
+	dst_prev->child = &rt->u.dst;
+	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		x->u.rt.fl = *fl;
+
+		dst_prev->dev = rt->u.dst.dev;
+		if (rt->u.dst.dev)
+			dev_hold(rt->u.dst.dev);
+		dst_prev->obsolete	= -1;
+		dst_prev->flags	       |= DST_HOST;
+		dst_prev->lastuse	= jiffies;
+		dst_prev->header_len	= header_len;
+		dst_prev->trailer_len	= trailer_len;
+		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
+		dst_prev->path		= &rt->u.dst;
+
+		/* Copy neighbout for reachability confirmation */
+		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
+		dst_prev->input		= rt->u.dst.input;
+		dst_prev->output	= dst_prev->xfrm->type->output;
+		if (rt->peer)
+			atomic_inc(&rt->peer->refcnt);
+		x->u.rt.peer = rt->peer;
+		/* Sheit... I remember I did this right. Apparently,
+		 * it was magically lost, so this code needs audit */
+		x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
+		x->u.rt.rt_type = rt->rt_type;
+		x->u.rt.rt_src = rt0->rt_src;
+		x->u.rt.rt_dst = rt0->rt_dst;
+		x->u.rt.rt_gateway = rt->rt_gateway;
+		x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
+		header_len -= x->u.dst.xfrm->props.header_len;
+		trailer_len -= x->u.dst.xfrm->props.trailer_len;
+	}
+	*dst_p = dst;
+	return 0;
+
+error:
+	if (dst)
+		dst_free(dst);
+	return err;
+}
+
+static void
+_decode_session4(struct sk_buff *skb, struct flowi *fl)
+{
+	struct iphdr *iph = skb->nh.iph;
+	u8 *xprth = skb->nh.raw + iph->ihl*4;
+
+	if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
+		switch (iph->protocol) {
+		case IPPROTO_UDP:
+		case IPPROTO_TCP:
+		case IPPROTO_SCTP:
+			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
+				u16 *ports = (u16 *)xprth;
+
+				fl->uli_u.ports.sport = ports[0];
+				fl->uli_u.ports.dport = ports[1];
+			}
+			break;
+
+		case IPPROTO_ESP:
+			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
+				u32 *ehdr = (u32 *)xprth;
+
+				fl->uli_u.spi = ehdr[0];
+			}
+			break;
+
+		case IPPROTO_AH:
+			if (pskb_may_pull(skb, xprth + 8 - skb->data)) {
+				u32 *ah_hdr = (u32*)xprth;
+
+				fl->uli_u.spi = ah_hdr[1];
+			}
+			break;
+
+		default:
+			fl->uli_u.spi = 0;
+			break;
+		};
+	} else {
+		memset(fl, 0, sizeof(struct flowi));
+	}
+	fl->proto = iph->protocol;
+	fl->fl4_dst = iph->daddr;
+	fl->fl4_src = iph->saddr;
+}
+
+static inline int xfrm4_garbage_collect(void)
+{
+	read_lock(&xfrm4_policy_afinfo.lock);
+	xfrm4_policy_afinfo.garbage_collect();
+	read_unlock(&xfrm4_policy_afinfo.lock);
+	return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
+}
+
+static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+	struct dst_entry *path = dst->path;
+
+	if (mtu < 68 + dst->header_len)
+		return;
+
+	path->ops->update_pmtu(path, mtu);
+}
+
+struct dst_ops xfrm4_dst_ops = {
+	.family =		AF_INET,
+	.protocol =		__constant_htons(ETH_P_IP),
+	.gc =			xfrm4_garbage_collect,
+	.update_pmtu =		xfrm4_update_pmtu,
+	.gc_thresh =		1024,
+	.entry_size =		sizeof(struct xfrm_dst),
+};
+
+struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
+	.family = 		AF_INET,
+	.lock = 		RW_LOCK_UNLOCKED,
+	.type_map = 		&xfrm4_type_map,
+	.dst_ops =		&xfrm4_dst_ops,
+	.dst_lookup =		xfrm4_dst_lookup,
+	.find_bundle = 		__xfrm4_find_bundle,
+	.bundle_create =	__xfrm4_bundle_create,
+	.decode_session =	_decode_session4,
+};
+
+void __init xfrm4_policy_init(void)
+{
+	xfrm_policy_register_afinfo(&xfrm4_policy_afinfo);
+}
+
+void __exit xfrm4_policy_fini(void)
+{
+	xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
+}
+
+void __init xfrm4_init(void)
+{
+	xfrm4_state_init();
+	xfrm4_policy_init();
+	xfrm4_input_init();
+}
+
+void __exit xfrm4_fini(void)
+{
+	//xfrm4_input_fini();
+	xfrm4_policy_fini();
+	xfrm4_state_fini();
+}
+
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm4_state.c linux-2.5.65-bk5/net/ipv4/xfrm4_state.c
--- linux-2.5.65-bk4/net/ipv4/xfrm4_state.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/net/ipv4/xfrm4_state.c	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,128 @@
+/*
+ * xfrm4_state.c
+ *
+ * Changes:
+ * 	YOSHIFUJI Hideaki @USAGI
+ * 		Split up af-specific portion
+ *
+ */
+
+#include <net/xfrm.h>
+#include <linux/pfkeyv2.h>
+#include <linux/ipsec.h>
+
+extern struct xfrm_state_afinfo xfrm4_state_afinfo;
+
+static void
+__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
+		     struct xfrm_tmpl *tmpl,
+		     xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
+	x->sel.daddr.a4 = fl->fl4_dst;
+	x->sel.saddr.a4 = fl->fl4_src;
+	x->sel.dport = fl->uli_u.ports.dport;
+	x->sel.dport_mask = ~0;
+	x->sel.sport = fl->uli_u.ports.sport;
+	x->sel.sport_mask = ~0;
+	x->sel.prefixlen_d = 32;
+	x->sel.prefixlen_s = 32;
+	x->sel.proto = fl->proto;
+	x->sel.ifindex = fl->oif;
+	x->id = tmpl->id;
+	if (x->id.daddr.a4 == 0)
+		x->id.daddr.a4 = daddr->a4;
+	x->props.saddr = tmpl->saddr;
+	if (x->props.saddr.a4 == 0)
+		x->props.saddr.a4 = saddr->a4;
+	x->props.mode = tmpl->mode;
+	x->props.reqid = tmpl->reqid;
+	x->props.family = AF_INET;
+}
+
+static struct xfrm_state *
+__xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
+{
+	unsigned h = __xfrm4_spi_hash(daddr, spi, proto);
+	struct xfrm_state *x;
+
+	list_for_each_entry(x, xfrm4_state_afinfo.state_byspi+h, byspi) {
+		if (x->props.family == AF_INET &&
+		    spi == x->id.spi &&
+		    daddr->a4 == x->id.daddr.a4 &&
+		    proto == x->id.proto) {
+			atomic_inc(&x->refcnt);
+			return x;
+		}
+	}
+	return NULL;
+}
+
+static struct xfrm_state *
+__xfrm4_find_acq(u8 mode, u16 reqid, u8 proto, 
+		 xfrm_address_t *daddr, xfrm_address_t *saddr, 
+		 int create)
+{
+	struct xfrm_state *x, *x0;
+	unsigned h = __xfrm4_dst_hash(daddr);
+
+	x0 = NULL;
+
+	list_for_each_entry(x, xfrm4_state_afinfo.state_bydst+h, bydst) {
+		if (x->props.family == AF_INET &&
+		    daddr->a4 == x->id.daddr.a4 &&
+		    mode == x->props.mode &&
+		    proto == x->id.proto &&
+		    saddr->a4 == x->props.saddr.a4 &&
+		    reqid == x->props.reqid &&
+		    x->km.state == XFRM_STATE_ACQ) {
+			    if (!x0)
+				    x0 = x;
+			    if (x->id.spi)
+				    continue;
+			    x0 = x;
+			    break;
+		    }
+	}
+	if (x0) {
+		atomic_inc(&x0->refcnt);
+	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
+		x0->sel.daddr.a4 = daddr->a4;
+		x0->sel.saddr.a4 = saddr->a4;
+		x0->sel.prefixlen_d = 32;
+		x0->sel.prefixlen_s = 32;
+		x0->props.saddr.a4 = saddr->a4;
+		x0->km.state = XFRM_STATE_ACQ;
+		x0->id.daddr.a4 = daddr->a4;
+		x0->id.proto = proto;
+		x0->props.family = AF_INET;
+		x0->props.mode = mode;
+		x0->props.reqid = reqid;
+		x0->props.family = AF_INET;
+		x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
+		atomic_inc(&x0->refcnt);
+		mod_timer(&x0->timer, jiffies + XFRM_ACQ_EXPIRES*HZ);
+		atomic_inc(&x0->refcnt);
+		list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h);
+		wake_up(&km_waitq);
+	}
+	return x0;
+}
+
+static struct xfrm_state_afinfo xfrm4_state_afinfo = {
+	.family			= AF_INET,
+	.lock			= RW_LOCK_UNLOCKED,
+	.init_tempsel		= __xfrm4_init_tempsel,
+	.state_lookup		= __xfrm4_state_lookup,
+	.find_acq		= __xfrm4_find_acq,
+};
+
+void __init xfrm4_state_init(void)
+{
+	xfrm_state_register_afinfo(&xfrm4_state_afinfo);
+}
+
+void __exit xfrm4_state_fini(void)
+{
+	xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
+}
+
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm_algo.c linux-2.5.65-bk5/net/ipv4/xfrm_algo.c
--- linux-2.5.65-bk4/net/ipv4/xfrm_algo.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/net/ipv4/xfrm_algo.c	Mon Mar 31 12:44:34 2003
@@ -219,6 +219,36 @@
 },
 };
 
+static struct xfrm_algo_desc calg_list[] = {
+{
+	.name = "deflate",
+	.uinfo = {
+		.comp = {
+			.threshold = 90,
+		}
+	},
+	.desc = { .sadb_alg_id = SADB_X_CALG_DEFLATE }
+},
+{
+	.name = "lzs",
+	.uinfo = {
+		.comp = {
+			.threshold = 90,
+		}
+	},
+	.desc = { .sadb_alg_id = SADB_X_CALG_LZS }
+},
+{
+	.name = "lzjh",
+	.uinfo = {
+		.comp = {
+			.threshold = 50,
+		}
+	},
+	.desc = { .sadb_alg_id = SADB_X_CALG_LZJH }
+},
+};
+
 static inline int aalg_entries(void)
 {
 	return sizeof(aalg_list) / sizeof(aalg_list[0]);
@@ -229,6 +259,12 @@
 	return sizeof(ealg_list) / sizeof(ealg_list[0]);
 }
 
+static inline int calg_entries(void)
+{
+	return sizeof(calg_list) / sizeof(calg_list[0]);
+}
+
+/* Todo: generic iterators */
 struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
 {
 	int i;
@@ -259,6 +295,21 @@
 	return NULL;
 }
 
+struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
+{
+	int i;
+
+	for (i = 0; i < calg_entries(); i++) {
+		if (calg_list[i].desc.sadb_alg_id == alg_id) {
+			if (calg_list[i].available)
+				return &calg_list[i];
+			else
+				break;
+		}
+	}
+	return NULL;
+}
+
 struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name)
 {
 	int i;
@@ -295,6 +346,24 @@
 	return NULL;
 }
 
+struct xfrm_algo_desc *xfrm_calg_get_byname(char *name)
+{
+	int i;
+
+	if (!name)
+		return NULL;
+
+	for (i=0; i < calg_entries(); i++) {
+		if (strcmp(name, calg_list[i].name) == 0) {
+			if (calg_list[i].available)
+				return &calg_list[i];
+			else
+				break;
+		}
+	}
+	return NULL;
+}
+
 struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
 {
 	if (idx >= aalg_entries())
@@ -311,6 +380,14 @@
 	return &ealg_list[idx];
 }
 
+struct xfrm_algo_desc *xfrm_calg_get_byidx(unsigned int idx)
+{
+	if (idx >= calg_entries())
+		return NULL;
+
+	return &calg_list[idx];
+}
+
 /*
  * Probe for the availability of crypto algorithms, and set the available
  * flag for any algorithms found on the system.  This is typically called by
@@ -334,6 +411,12 @@
 		if (ealg_list[i].available != status)
 			ealg_list[i].available = status;
 	}
+	
+	for (i = 0; i < calg_entries(); i++) {
+		status = crypto_alg_available(calg_list[i].name, 0);
+		if (calg_list[i].available != status)
+			calg_list[i].available = status;
+	}
 #endif
 }
 
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm_input.c linux-2.5.65-bk5/net/ipv4/xfrm_input.c
--- linux-2.5.65-bk4/net/ipv4/xfrm_input.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/net/ipv4/xfrm_input.c	Mon Mar 31 12:44:34 2003
@@ -1,178 +1,26 @@
-/* Changes
+/*
+ * xfrm_input.c
  *
- *	Mitsuru KANDA @USAGI       : IPv6 Support 
- * 	Kazunori MIYAZAWA @USAGI   :
- * 	YOSHIFUJI Hideaki @USAGI   :
- * 	Kunihiro Ishiguro          :
+ * Changes:
+ * 	YOSHIFUJI Hideaki @USAGI
+ * 		Split up af-specific portion
  * 	
  */
 
 #include <net/ip.h>
-#include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static kmem_cache_t *secpath_cachep;
-
 void __secpath_destroy(struct sec_path *sp)
 {
 	int i;
 	for (i = 0; i < sp->len; i++)
 		xfrm_state_put(sp->xvec[i]);
-	kmem_cache_free(secpath_cachep, sp);
-}
-
-/* Fetch spi and seq frpm ipsec header */
-
-static int xfrm_parse_spi(struct sk_buff *skb, u32 *spi, u32 *seq)
-{
-	int offset, offset_seq;
-
-	switch (skb->nh.iph->protocol) {
-	case IPPROTO_AH:
-		offset = offsetof(struct ip_auth_hdr, spi);
-		offset_seq = offsetof(struct ip_auth_hdr, seq_no);
-		break;
-	case IPPROTO_ESP:
-		offset = offsetof(struct ip_esp_hdr, spi);
-		offset_seq = offsetof(struct ip_esp_hdr, seq_no);
-		break;
-	case IPPROTO_COMP:
-		if (!pskb_may_pull(skb, 4))
-			return -EINVAL;
-		*spi = *(u16*)(skb->h.raw + 2);
-		*seq = 0;
-		return 0;
-	default:
-		return 1;
-	}
-
-	if (!pskb_may_pull(skb, 16))
-		return -EINVAL;
-
-	*spi = *(u32*)(skb->h.raw + offset);
-	*seq = *(u32*)(skb->h.raw + offset_seq);
-	return 0;
-}
-
-
-
-int xfrm4_rcv(struct sk_buff *skb)
-{
-	int err;
-	u32 spi, seq;
-	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
-	struct xfrm_state *x;
-	int xfrm_nr = 0;
-	int decaps = 0;
-
-	if ((err = xfrm_parse_spi(skb, &spi, &seq)) != 0)
-		goto drop;
-
-	do {
-		struct iphdr *iph = skb->nh.iph;
-
-		if (xfrm_nr == XFRM_MAX_DEPTH)
-			goto drop;
-
-		x = xfrm4_state_lookup(iph->daddr, spi, iph->protocol);
-		if (x == NULL)
-			goto drop;
-
-		spin_lock(&x->lock);
-		if (unlikely(x->km.state != XFRM_STATE_VALID))
-			goto drop_unlock;
-
-		if (x->props.replay_window && xfrm_replay_check(x, seq))
-			goto drop_unlock;
-
-		if (x->type->input(x, skb))
-			goto drop_unlock;
-
-		if (x->props.replay_window)
-			xfrm_replay_advance(x, seq);
-
-		x->curlft.bytes += skb->len;
-		x->curlft.packets++;
-
-		spin_unlock(&x->lock);
-
-		xfrm_vec[xfrm_nr++] = x;
-
-		iph = skb->nh.iph;
-
-		if (x->props.mode) {
-			if (iph->protocol != IPPROTO_IPIP)
-				goto drop;
-			skb->nh.raw = skb->data;
-			iph = skb->nh.iph;
-			memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-			decaps = 1;
-			break;
-		}
-
-		if ((err = xfrm_parse_spi(skb, &spi, &seq)) < 0)
-			goto drop;
-	} while (!err);
-
-	/* Allocate new secpath or COW existing one. */
-
-	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
-		struct sec_path *sp;
-		sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC);
-		if (!sp)
-			goto drop;
-		if (skb->sp) {
-			memcpy(sp, skb->sp, sizeof(struct sec_path));
-			secpath_put(skb->sp);
-		} else
-			sp->len = 0;
-		atomic_set(&sp->refcnt, 1);
-		skb->sp = sp;
-	}
-	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
-		goto drop;
-
-	memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*));
-	skb->sp->len += xfrm_nr;
-
-	if (decaps) {
-		if (!(skb->dev->flags&IFF_LOOPBACK)) {
-			dst_release(skb->dst);
-			skb->dst = NULL;
-		}
-		netif_rx(skb);
-		return 0;
-	} else {
-		return -skb->nh.iph->protocol;
-	}
-
-drop_unlock:
-	spin_unlock(&x->lock);
-	xfrm_state_put(x);
-drop:
-	while (--xfrm_nr >= 0)
-		xfrm_state_put(xfrm_vec[xfrm_nr]);
-	kfree_skb(skb);
-	return 0;
-}
-
-
-void __init xfrm_input_init(void)
-{
-	secpath_cachep = kmem_cache_create("secpath_cache",
-					   sizeof(struct sec_path),
-					   0, SLAB_HWCACHE_ALIGN,
-					   NULL, NULL);
-
-	if (!secpath_cachep)
-		panic("IP: failed to allocate secpath_cache\n");
+	kmem_cache_free(sp->pool, sp);
 }
 
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-
 /* Fetch spi and seq frpm ipsec header */
 
-static int xfrm6_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
 {
 	int offset, offset_seq;
 
@@ -188,7 +36,7 @@
 	case IPPROTO_COMP:
 		if (!pskb_may_pull(skb, 4))
 			return -EINVAL;
-		*spi = *(u16*)(skb->h.raw + 2);
+		*spi = ntohl(ntohs(*(u16*)(skb->h.raw + 2)));
 		*seq = 0;
 		return 0;
 	default:
@@ -202,253 +50,3 @@
 	*seq = *(u32*)(skb->h.raw + offset_seq);
 	return 0;
 }
-
-static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
-{
-	u8 *opt = (u8 *)opthdr;
-	int len = ipv6_optlen(opthdr);
-	int off = 0;
-	int optlen = 0;
-
-	off += 2;
-	len -= 2;
-
-	while (len > 0) {
-
-		switch (opt[off]) {
-
-		case IPV6_TLV_PAD0:
-			optlen = 1;
-			break;
-		default:
-			if (len < 2) 
-				goto bad;
-			optlen = opt[off+1]+2;
-			if (len < optlen)
-				goto bad;
-			if (opt[off] & 0x20)
-				memset(&opt[off+2], 0, opt[off+1]);
-			break;
-		}
-
-		off += optlen;
-		len -= optlen;
-	}
-	if (len == 0)
-		return 1;
-
-bad:
-	return 0;
-}
-
-int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
-{
-	u16 offset = sizeof(struct ipv6hdr);
-	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-	unsigned int packet_len = skb->tail - skb->nh.raw;
-	u8 nexthdr = skb->nh.ipv6h->nexthdr;
-	u8 nextnexthdr = 0;
-
-	*nh_offset = ((unsigned char *)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
-
-	while (offset + 1 <= packet_len) {
-
-		switch (nexthdr) {
-
-		case NEXTHDR_HOP:
-			*nh_offset = offset;
-			offset += ipv6_optlen(exthdr);
-			if (!zero_out_mutable_opts(exthdr)) {
-				if (net_ratelimit())
-					printk(KERN_WARNING "overrun hopopts\n"); 
-				return 0;
-			}
-			nexthdr = exthdr->nexthdr;
-			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-			break;
-
-		case NEXTHDR_ROUTING:
-			*nh_offset = offset;
-			offset += ipv6_optlen(exthdr);
-			((struct ipv6_rt_hdr*)exthdr)->segments_left = 0; 
-			nexthdr = exthdr->nexthdr;
-			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-			break;
-
-		case NEXTHDR_DEST:
-			*nh_offset = offset;
-			offset += ipv6_optlen(exthdr);
-			if (!zero_out_mutable_opts(exthdr))  {
-				if (net_ratelimit())
-					printk(KERN_WARNING "overrun destopt\n"); 
-				return 0;
-			}
-			nexthdr = exthdr->nexthdr;
-			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-			break;
-
-		case NEXTHDR_AUTH:
-			if (dir == XFRM_POLICY_OUT) {
-				memset(((struct ipv6_auth_hdr*)exthdr)->auth_data, 0, 
-				       (((struct ipv6_auth_hdr*)exthdr)->hdrlen - 1) << 2);
-			}
-			if (exthdr->nexthdr == NEXTHDR_DEST) {
-				offset += (((struct ipv6_auth_hdr*)exthdr)->hdrlen + 2) << 2;
-				exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-				nextnexthdr = exthdr->nexthdr;
-				if (!zero_out_mutable_opts(exthdr)) {
-					if (net_ratelimit())
-						printk(KERN_WARNING "overrun destopt\n");
-					return 0;
-				}
-			}
-			return nexthdr;
-		default :
-			return nexthdr;
-		}
-	}
-
-	return nexthdr;
-}
-
-int xfrm6_rcv(struct sk_buff *skb)
-{
-	int err;
-	u32 spi, seq;
-	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
-	struct xfrm_state *x;
-	int xfrm_nr = 0;
-	int decaps = 0;
-	struct ipv6hdr *hdr = skb->nh.ipv6h;
-	unsigned char *tmp_hdr = NULL;
-	int hdr_len = 0;
-	u16 nh_offset = 0;
-	u8 nexthdr = 0;
-
-	if (hdr->nexthdr == IPPROTO_AH || hdr->nexthdr == IPPROTO_ESP) {
-		nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
-		hdr_len = sizeof(struct ipv6hdr);
-	} else {
-		hdr_len = skb->h.raw - skb->nh.raw;
-	}
-
-	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
-	if (!tmp_hdr)
-		goto drop;
-	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
-
-	nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN);
-	hdr->priority    = 0;
-	hdr->flow_lbl[0] = 0;
-	hdr->flow_lbl[1] = 0;
-	hdr->flow_lbl[2] = 0;
-	hdr->hop_limit   = 0;
-
-	if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
-		goto drop;
-	
-	do {
-		struct ipv6hdr *iph = skb->nh.ipv6h;
-
-		if (xfrm_nr == XFRM_MAX_DEPTH)
-			goto drop;
-
-		x = xfrm6_state_lookup(&iph->daddr, spi, nexthdr);
-		if (x == NULL)
-			goto drop;
-		spin_lock(&x->lock);
-		if (unlikely(x->km.state != XFRM_STATE_VALID))
-			goto drop_unlock;
-
-		if (x->props.replay_window && xfrm_replay_check(x, seq))
-			goto drop_unlock;
-
-		nexthdr = x->type->input(x, skb);
-		if (nexthdr <= 0)
-			goto drop_unlock;
-
-		if (x->props.replay_window)
-			xfrm_replay_advance(x, seq);
-
-		x->curlft.bytes += skb->len;
-		x->curlft.packets++;
-
-		spin_unlock(&x->lock);
-
-		xfrm_vec[xfrm_nr++] = x;
-
-		iph = skb->nh.ipv6h; /* ??? */ 
-
-		if (nexthdr == NEXTHDR_DEST) {
-			if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
-		    	!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
-				err = -EINVAL;
-				goto drop;
-			}
-			nexthdr = skb->h.raw[0];
-			nh_offset = skb->h.raw - skb->nh.raw;
-			skb_pull(skb, (skb->h.raw[1]+1)<<3);
-			skb->h.raw = skb->data;
-		}
-
-		if (x->props.mode) { /* XXX */
-			if (iph->nexthdr != IPPROTO_IPV6)
-				goto drop;
-			skb->nh.raw = skb->data;
-			iph = skb->nh.ipv6h;
-			decaps = 1;
-			break;
-		}
-
-		if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
-			goto drop;
-	} while (!err);
-
-	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-	skb->nh.raw[nh_offset] = nexthdr;
-	skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
-
-	/* Allocate new secpath or COW existing one. */
-	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
-		struct sec_path *sp;
-		sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC);
-		if (!sp)
-			goto drop;
-		if (skb->sp) {
-			memcpy(sp, skb->sp, sizeof(struct sec_path));
-			secpath_put(skb->sp);
-		} else
-			sp->len = 0;
-		atomic_set(&sp->refcnt, 1);
-		skb->sp = sp;
-	}
-
-	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
-		goto drop;
-
-	memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*));
-	skb->sp->len += xfrm_nr;
-
-	if (decaps) {
-		if (!(skb->dev->flags&IFF_LOOPBACK)) {
-			dst_release(skb->dst);
-			skb->dst = NULL;
-		}
-		netif_rx(skb);
-		return 0;
-	} else {
-		return -nexthdr;
-	}
-
-drop_unlock:
-	spin_unlock(&x->lock);
-	xfrm_state_put(x);
-drop:
-	if (tmp_hdr) kfree(tmp_hdr);
-	while (--xfrm_nr >= 0)
-		xfrm_state_put(xfrm_vec[xfrm_nr]);
-	kfree_skb(skb);
-	return 0;
-}
-
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm_policy.c linux-2.5.65-bk5/net/ipv4/xfrm_policy.c
--- linux-2.5.65-bk4/net/ipv4/xfrm_policy.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/xfrm_policy.c	Mon Mar 31 12:44:34 2003
@@ -1,16 +1,20 @@
-/* Changes
+/* 
+ * xfrm_policy.c
  *
- *	Mitsuru KANDA @USAGI       : IPv6 Support 
- * 	Kazunori MIYAZAWA @USAGI   :
- * 	Kunihiro Ishiguro          :
+ * Changes:
+ *	Mitsuru KANDA @USAGI
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	Kunihiro Ishiguro
+ * 		IPv6 support
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	YOSHIFUJI Hideaki
+ * 		Split up af-specific portion
  * 	
  */
 
 #include <linux/config.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/ip6_route.h>
 
 DECLARE_MUTEX(xfrm_cfg_sem);
 
@@ -19,12 +23,10 @@
 
 struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
-extern struct dst_ops xfrm4_dst_ops;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-extern struct dst_ops xfrm6_dst_ops;
-#endif
+static rwlock_t xfrm_policy_afinfo_lock = RW_LOCK_UNLOCKED;
+static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
 
-static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
+kmem_cache_t *xfrm_dst_cache;
 
 /* Limited flow cache. Its function now is to accelerate search for
  * policy rules.
@@ -49,40 +51,8 @@
 
 struct flow_entry **flow_table;
 
-#define FLOWCACHE_HASH_SIZE	1024
-
-static inline u32 flow_hash(struct flowi *fl)
-{
-	u32 hash = fl->fl4_src ^ fl->uli_u.ports.sport;
-
-	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-	hash ^= fl->fl4_dst ^ fl->uli_u.ports.dport;
-	hash ^= (hash >> 10);
-	hash ^= (hash >> 20);
-	return hash & (FLOWCACHE_HASH_SIZE-1);
-}
-
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-static inline u32 flow_hash6(struct flowi *fl)
-{
-	u32 hash = fl->fl6_src->s6_addr32[2] ^
-		   fl->fl6_src->s6_addr32[3] ^ 
-		   fl->uli_u.ports.sport;
-
-	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-	hash ^= fl->fl6_dst->s6_addr32[2] ^
-		fl->fl6_dst->s6_addr32[3] ^ 
-		fl->uli_u.ports.dport;
-	hash ^= (hash >> 10);
-	hash ^= (hash >> 20);
-	return hash & (FLOWCACHE_HASH_SIZE-1);
-}
-#endif
-
-static int flow_lwm = 2*FLOWCACHE_HASH_SIZE;
-static int flow_hwm = 4*FLOWCACHE_HASH_SIZE;
+static int flow_lwm = 2*XFRM_FLOWCACHE_HASH_SIZE;
+static int flow_hwm = 4*XFRM_FLOWCACHE_HASH_SIZE;
 
 static int flow_number[NR_CPUS] __cacheline_aligned;
 
@@ -92,11 +62,11 @@
 {
 	int i;
 	struct flow_entry *fle, **flp;
-	int shrink_to = flow_lwm/FLOWCACHE_HASH_SIZE;
+	int shrink_to = flow_lwm/XFRM_FLOWCACHE_HASH_SIZE;
 
-	for (i=0; i<FLOWCACHE_HASH_SIZE; i++) {
+	for (i=0; i<XFRM_FLOWCACHE_HASH_SIZE; i++) {
 		int k = 0;
-		flp = &flow_table[cpu*FLOWCACHE_HASH_SIZE+i];
+		flp = &flow_table[cpu*XFRM_FLOWCACHE_HASH_SIZE+i];
 		while ((fle=*flp) != NULL && k<shrink_to) {
 			k++;
 			flp = &fle->next;
@@ -118,23 +88,12 @@
 	u32 hash;
 	int cpu;
 
-	switch (family) {
-	case AF_INET:
-		hash = flow_hash(fl);
-		break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		hash = flow_hash6(fl);
-		break;
-#endif
-	default:
-		return NULL;
-	}
+	hash = flow_hash(fl, family);
 
 	local_bh_disable();
 	cpu = smp_processor_id();
 
-	for (fle = flow_table[cpu*FLOWCACHE_HASH_SIZE+hash];
+	for (fle = flow_table[cpu*XFRM_FLOWCACHE_HASH_SIZE+hash];
 	     fle; fle = fle->next) {
 		if (memcmp(fl, &fle->fl, sizeof(fle->fl)) == 0 &&
 		    fle->dir == dir) {
@@ -172,8 +131,8 @@
 			fle->pol = pol;
 			if (pol)
 				atomic_inc(&pol->refcnt);
-			fle->next = flow_table[cpu*FLOWCACHE_HASH_SIZE+hash];
-			flow_table[cpu*FLOWCACHE_HASH_SIZE+hash] = fle;
+			fle->next = flow_table[cpu*XFRM_FLOWCACHE_HASH_SIZE+hash];
+			flow_table[cpu*XFRM_FLOWCACHE_HASH_SIZE+hash] = fle;
 		}
 	}
 	local_bh_enable();
@@ -193,7 +152,7 @@
 		panic("NET: failed to allocate flow cache slab\n");
 
 	for (order = 0;
-	     (PAGE_SIZE<<order) < (NR_CPUS*sizeof(struct flow_entry *)*FLOWCACHE_HASH_SIZE);
+	     (PAGE_SIZE<<order) < (NR_CPUS*sizeof(struct flow_entry *)*XFRM_FLOWCACHE_HASH_SIZE);
 	     order++)
 		/* NOTHING */;
 
@@ -205,130 +164,82 @@
 	memset(flow_table, 0, PAGE_SIZE<<order);
 }
 
-static struct xfrm_type *xfrm_type_map[256];
-static rwlock_t xfrm_type_lock = RW_LOCK_UNLOCKED;
-
-int xfrm_register_type(struct xfrm_type *type)
+int xfrm_register_type(struct xfrm_type *type, unsigned short family)
 {
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	struct xfrm_type_map *typemap;
 	int err = 0;
 
-	write_lock(&xfrm_type_lock);
-	if (xfrm_type_map[type->proto] == NULL)
-		xfrm_type_map[type->proto] = type;
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
+	typemap = afinfo->type_map;
+
+	write_lock(&typemap->lock);
+	if (likely(typemap->map[type->proto] == NULL))
+		typemap->map[type->proto] = type;
 	else
 		err = -EEXIST;
-	write_unlock(&xfrm_type_lock);
+	write_unlock(&typemap->lock);
+	xfrm_policy_put_afinfo(afinfo);
 	return err;
 }
 
-int xfrm_unregister_type(struct xfrm_type *type)
+int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
 {
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	struct xfrm_type_map *typemap;
 	int err = 0;
 
-	write_lock(&xfrm_type_lock);
-	if (xfrm_type_map[type->proto] != type)
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
+	typemap = afinfo->type_map;
+
+	write_lock(&typemap->lock);
+	if (unlikely(typemap->map[type->proto] != type))
 		err = -ENOENT;
 	else
-		xfrm_type_map[type->proto] = NULL;
-	write_unlock(&xfrm_type_lock);
+		typemap->map[type->proto] = NULL;
+	write_unlock(&typemap->lock);
+	xfrm_policy_put_afinfo(afinfo);
 	return err;
 }
 
-struct xfrm_type *xfrm_get_type(u8 proto)
+struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
 {
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	struct xfrm_type_map *typemap;
 	struct xfrm_type *type;
 
-	read_lock(&xfrm_type_lock);
-	type = xfrm_type_map[proto];
-	if (type && !try_module_get(type->owner))
+	if (unlikely(afinfo == NULL))
+		return NULL;
+	typemap = afinfo->type_map;
+
+	read_lock(&typemap->lock);
+	type = typemap->map[proto];
+	if (unlikely(type && !try_module_get(type->owner)))
 		type = NULL;
-	read_unlock(&xfrm_type_lock);
+	read_unlock(&typemap->lock);
+	xfrm_policy_put_afinfo(afinfo);
 	return type;
 }
 
-static  xfrm_dst_lookup_t *__xfrm_dst_lookup[AF_MAX];
-rwlock_t xdl_lock = RW_LOCK_UNLOCKED;
-
-int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, 
-			     unsigned short family)
+int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
+		    unsigned short family)
 {
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
 	int err = 0;
 
-	write_lock(&xdl_lock);
-	if (__xfrm_dst_lookup[family])
-		err = -ENOBUFS;
-	else { 
-		__xfrm_dst_lookup[family] = dst_lookup;
-	}
-	write_unlock(&xdl_lock);
-
-	return err;
-}
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
 
-void xfrm_dst_lookup_unregister(unsigned short family)
-{
-	write_lock(&xdl_lock);
-	if (__xfrm_dst_lookup[family])
-		__xfrm_dst_lookup[family] = 0;
-	write_unlock(&xdl_lock);
-}
-
-static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
-				  unsigned short family)
-{
-	int err = 0;
-	read_lock(&xdl_lock);
-	if (__xfrm_dst_lookup[family])
-		err = __xfrm_dst_lookup[family](dst, fl);
+	if (likely(afinfo->dst_lookup != NULL))
+		err = afinfo->dst_lookup(dst, fl);
 	else
 		err = -EINVAL;
-	read_unlock(&xdl_lock);
+	xfrm_policy_put_afinfo(afinfo);
 	return err;
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static struct xfrm_type *xfrm6_type_map[256];
-static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
-
-int xfrm6_register_type(struct xfrm_type *type)
-{
-	int err = 0;
-
-	write_lock(&xfrm6_type_lock);
-	if (xfrm6_type_map[type->proto] == NULL)
-		xfrm6_type_map[type->proto] = type;
-	else
-		err = -EEXIST;
-	write_unlock(&xfrm6_type_lock);
-	return err;
-}
-
-int xfrm6_unregister_type(struct xfrm_type *type)
-{
-	int err = 0;
-
-	write_lock(&xfrm6_type_lock);
-	if (xfrm6_type_map[type->proto] != type)
-		err = -ENOENT;
-	else
-		xfrm6_type_map[type->proto] = NULL;
-	write_unlock(&xfrm6_type_lock);
-	return err;
-}
-
-struct xfrm_type *xfrm6_get_type(u8 proto)
-{
-	struct xfrm_type *type;
-
-	read_lock(&xfrm6_type_lock);
-	type = xfrm6_type_map[proto];
-	if (type && !try_module_get(type->owner))
-		type = NULL;
-	read_unlock(&xfrm6_type_lock);
-	return type;
-}
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
-
 void xfrm_put_type(struct xfrm_type *type)
 {
 	module_put(type->owner);
@@ -608,18 +519,7 @@
 		if (pol->family != family)
 			continue;
 
-		switch (family) {
-		case AF_INET:
-			match = xfrm4_selector_match(sel, fl);
-			break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			match = xfrm6_selector_match(sel, fl);
-			break;
-#endif
-		default:
-			match = 0;
-		}
+		match = xfrm_selector_match(sel, fl, family);
 		if (match) {
 			atomic_inc(&pol->refcnt);
 			break;
@@ -637,18 +537,7 @@
 	if ((pol = sk->policy[dir]) != NULL) {
 		int match;
 
-		switch (sk->family) {
-		case AF_INET:
-			match = xfrm4_selector_match(&pol->selector, fl);
-			break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			match = xfrm6_selector_match(&pol->selector, fl);
-			break;
-#endif
-		default:
-			match = 0;
-		}
+		match = xfrm_selector_match(&pol->selector, fl, sk->family);
 		if (match)
 			atomic_inc(&pol->refcnt);
 		else
@@ -750,26 +639,27 @@
 /* Resolve list of templates for the flow, given policy. */
 
 static int
-xfrm4_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
-		   struct xfrm_state **xfrm)
+xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
+		  struct xfrm_state **xfrm,
+		  unsigned short family)
 {
 	int nx;
 	int i, error;
-	u32 daddr = fl->fl4_dst;
-	u32 saddr = fl->fl4_src;
+	xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family);
+	xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family);
 
 	for (nx=0, i = 0; i < policy->xfrm_nr; i++) {
 		struct xfrm_state *x;
-		u32 remote = daddr;
-		u32 local = saddr;
+		xfrm_address_t *remote = daddr;
+		xfrm_address_t *local  = saddr;
 		struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
 
 		if (tmpl->mode) {
-			remote = tmpl->id.daddr.xfrm4_addr;
-			local = tmpl->saddr.xfrm4_addr;
+			remote = &tmpl->id.daddr;
+			local = &tmpl->saddr;
 		}
 
-		x = xfrm4_state_find(remote, local, fl, tmpl, policy, &error);
+		x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family);
 
 		if (x && x->km.state == XFRM_STATE_VALID) {
 			xfrm[nx++] = x;
@@ -794,91 +684,21 @@
 	return error;
 }
 
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-static int
-xfrm6_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
-		  struct xfrm_state **xfrm)
-{
-	int nx;
-	int i, error;
-	struct in6_addr *daddr = fl->fl6_dst;
-	struct in6_addr *saddr = fl->fl6_src;
-
-	for (nx=0, i = 0; i < policy->xfrm_nr; i++) {
-		struct xfrm_state *x=NULL;
-		struct in6_addr *remote = daddr;
-		struct in6_addr *local = saddr;
-		struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
-
-		if (tmpl->mode) {
-			remote = (struct in6_addr*)&tmpl->id.daddr;
-			local = (struct in6_addr*)&tmpl->saddr;
-		}
-
-		x = xfrm6_state_find(remote, local, fl, tmpl, policy, &error);
-
-		if (x && x->km.state == XFRM_STATE_VALID) {
-			xfrm[nx++] = x;
-			daddr = remote;
-			saddr = local;
-			continue;
-		}
-		if (x) {
-			error = (x->km.state == XFRM_STATE_ERROR ?
-				 -EINVAL : -EAGAIN);
-			xfrm_state_put(x);
-		}
-
-		if (!tmpl->optional)
-			goto fail;
-	}
-	return nx;
-
-fail:
-	for (nx--; nx>=0; nx--)
-		xfrm_state_put(xfrm[nx]);
-	return error;
-}
-#endif
-
 /* Check that the bundle accepts the flow and its components are
  * still valid.
  */
 
-static int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
-{
-	do {
-		if (xdst->u.dst.ops != &xfrm4_dst_ops)
-			return 1;
-
-		if (!xfrm4_selector_match(&xdst->u.dst.xfrm->sel, fl))
-			return 0;
-		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
-		    xdst->u.dst.path->obsolete > 0)
-			return 0;
-		xdst = (struct xfrm_dst*)xdst->u.dst.child;
-	} while (xdst);
-	return 0;
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static int xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
+static struct dst_entry *
+xfrm_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy, unsigned short family)
 {
-	do {
-		if (xdst->u.dst.ops != &xfrm6_dst_ops)
-			return 1;
-
-		if (!xfrm6_selector_match(&xdst->u.dst.xfrm->sel, fl))
-			return 0;
-		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
-		    xdst->u.dst.path->obsolete > 0)
-			return 0;
-		xdst = (struct xfrm_dst*)xdst->u.dst.child;
-	} while (xdst);
-	return 0;
+	struct dst_entry *x;
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	if (unlikely(afinfo == NULL))
+		return ERR_PTR(-EINVAL);
+	x = afinfo->find_bundle(fl, rt, policy);
+	xfrm_policy_put_afinfo(afinfo);
+	return x;
 }
-#endif
-
 
 /* Allocate chain of dst_entry's, attach known xfrm's, calculate
  * all the metrics... Shortly, bundle a bundle.
@@ -886,195 +706,18 @@
 
 static int
 xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
-		   struct flowi *fl, struct dst_entry **dst_p)
+		   struct flowi *fl, struct dst_entry **dst_p,
+		   unsigned short family)
 {
-	struct dst_entry *dst, *dst_prev;
-	struct rtable *rt0 = (struct rtable*)(*dst_p);
-	struct rtable *rt = rt0;
-	u32 remote = fl->fl4_dst;
-	u32 local  = fl->fl4_src;
-	int i;
 	int err;
-	int header_len = 0;
-	int trailer_len = 0;
-
-	dst = dst_prev = NULL;
-
-	for (i = 0; i < nx; i++) {
-		struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
-
-		if (unlikely(dst1 == NULL)) {
-			err = -ENOBUFS;
-			goto error;
-		}
-
-		dst1->xfrm = xfrm[i];
-		if (!dst)
-			dst = dst1;
-		else {
-			dst_prev->child = dst1;
-			dst1->flags |= DST_NOHASH;
-			dst_hold(dst1);
-		}
-		dst_prev = dst1;
-		if (xfrm[i]->props.mode) {
-			remote = xfrm[i]->id.daddr.xfrm4_addr;
-			local  = xfrm[i]->props.saddr.xfrm4_addr;
-		}
-		header_len += xfrm[i]->props.header_len;
-		trailer_len += xfrm[i]->props.trailer_len;
-	}
-
-	if (remote != fl->fl4_dst) {
-		struct flowi fl_tunnel = { .nl_u = { .ip4_u =
-						     { .daddr = remote,
-						       .saddr = local }
-					           }
-				         };
-		err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET);
-		if (err)
-			goto error;
-	} else {
-		dst_hold(&rt->u.dst);
-	}
-	dst_prev->child = &rt->u.dst;
-	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
-		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
-		x->u.rt.fl = *fl;
-
-		dst_prev->dev = rt->u.dst.dev;
-		if (rt->u.dst.dev)
-			dev_hold(rt->u.dst.dev);
-		dst_prev->obsolete	= -1;
-		dst_prev->flags	       |= DST_HOST;
-		dst_prev->lastuse	= jiffies;
-		dst_prev->header_len	= header_len;
-		dst_prev->trailer_len	= trailer_len;
-		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
-		dst_prev->path		= &rt->u.dst;
-
-		/* Copy neighbout for reachability confirmation */
-		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
-		dst_prev->input		= rt->u.dst.input;
-		dst_prev->output	= dst_prev->xfrm->type->output;
-		if (rt->peer)
-			atomic_inc(&rt->peer->refcnt);
-		x->u.rt.peer = rt->peer;
-		/* Sheit... I remember I did this right. Apparently,
-		 * it was magically lost, so this code needs audit */
-		x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
-		x->u.rt.rt_type = rt->rt_type;
-		x->u.rt.rt_src = rt0->rt_src;
-		x->u.rt.rt_dst = rt0->rt_dst;
-		x->u.rt.rt_gateway = rt->rt_gateway;
-		x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
-		header_len -= x->u.dst.xfrm->props.header_len;
-		trailer_len -= x->u.dst.xfrm->props.trailer_len;
-	}
-	*dst_p = dst;
-	return 0;
-
-error:
-	if (dst)
-		dst_free(dst);
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	err = afinfo->bundle_create(policy, xfrm, nx, fl, dst_p);
+	xfrm_policy_put_afinfo(afinfo);
 	return err;
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static int
-xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
-		   struct flowi *fl, struct dst_entry **dst_p)
-{
-	struct dst_entry *dst, *dst_prev;
-	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
-	struct rt6_info *rt  = rt0;
-	struct in6_addr *remote = fl->fl6_dst;
-	struct in6_addr *local  = fl->fl6_src;
-	int i;
-	int err = 0;
-	int header_len = 0;
-	int trailer_len = 0;
-
-	dst = dst_prev = NULL;
-
-	for (i = 0; i < nx; i++) {
-		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
-
-		if (unlikely(dst1 == NULL)) {
-			err = -ENOBUFS;
-			goto error;
-		}
-
-		dst1->xfrm = xfrm[i];
-		if (!dst)
-			dst = dst1;
-		else {
-			dst_prev->child = dst1;
-			dst1->flags |= DST_NOHASH;
-			dst_clone(dst1);
-		}
-		dst_prev = dst1;
-		if (xfrm[i]->props.mode) {
-			remote = (struct in6_addr*)&xfrm[i]->id.daddr;
-			local  = (struct in6_addr*)&xfrm[i]->props.saddr;
-		}
-		header_len += xfrm[i]->props.header_len;
-		trailer_len += xfrm[i]->props.trailer_len;
-	}
-
-	if (ipv6_addr_cmp(remote, fl->fl6_dst)) {
-		struct flowi fl_tunnel = { .nl_u = { .ip6_u =
-						     { .daddr = remote,
-						       .saddr = local }
-					           }
-				         };
-		err = xfrm_dst_lookup((struct xfrm_dst**)&dst, &fl_tunnel, AF_INET6);
-		if (err)
-			goto error;
-	} else {
-		dst_clone(&rt->u.dst);
-	}
-	dst_prev->child = &rt->u.dst;
-	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
-		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
-		x->u.rt.fl = *fl;
-
-		dst_prev->dev = rt->u.dst.dev;
-		if (rt->u.dst.dev)
-			dev_hold(rt->u.dst.dev);
-		dst_prev->obsolete	= -1;
-		dst_prev->flags	       |= DST_HOST;
-		dst_prev->lastuse	= jiffies;
-		dst_prev->header_len	= header_len;
-		dst_prev->trailer_len	= trailer_len;
-		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
-		dst_prev->path		= &rt->u.dst;
-
-		/* Copy neighbout for reachability confirmation */
-		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
-		dst_prev->input		= rt->u.dst.input;
-		dst_prev->output	= dst_prev->xfrm->type->output;
-		/* Sheit... I remember I did this right. Apparently,
-		 * it was magically lost, so this code needs audit */
-		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
-		x->u.rt6.rt6i_metric   = rt0->rt6i_metric;
-		x->u.rt6.rt6i_node     = rt0->rt6i_node;
-		x->u.rt6.rt6i_hoplimit = rt0->rt6i_hoplimit;
-		x->u.rt6.rt6i_gateway  = rt0->rt6i_gateway;
-		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 
-		header_len -= x->u.dst.xfrm->props.header_len;
-		trailer_len -= x->u.dst.xfrm->props.trailer_len;
-	}
-	*dst_p = dst;
-	return 0;
-
-error:
-	if (dst)
-		dst_free(dst);
-	return err;
-}
-#endif
-
 /* Main function: finds/creates a bundle for given flow.
  *
  * At the moment we eat a raw IP route. Mostly to speed up lookups
@@ -1141,46 +784,17 @@
 		 * LATER: help from flow cache. It is optional, this
 		 * is required only for output policy.
 		 */
-		if (family == AF_INET) {
-			read_lock_bh(&policy->lock);
-			for (dst = policy->bundles; dst; dst = dst->next) {
-				struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
-				if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
-				    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
-				    xdst->u.rt.fl.oif == fl->oif &&
-				    xfrm_bundle_ok(xdst, fl)) {
-					dst_clone(dst);
-					break;
-				}
-			}
-			read_unlock_bh(&policy->lock);
-			if (dst)
-				break;
-			nx = xfrm4_tmpl_resolve(policy, fl, xfrm);
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-		} else if (family == AF_INET6) {
-			read_lock_bh(&policy->lock);
-			for (dst = policy->bundles; dst; dst = dst->next) {
-				struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
-				if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, fl->fl6_dst) &&
-				    !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, fl->fl6_src) &&
-				    xfrm6_bundle_ok(xdst, fl)) {
-					dst_clone(dst);
-					break;
-				}
-			}
-			read_unlock_bh(&policy->lock);
-			if (dst)
-				break;
-			nx = xfrm6_tmpl_resolve(policy, fl, xfrm);
-#endif
-		} else {
-			return -EINVAL;
+		dst = xfrm_find_bundle(fl, rt, policy, family);
+		if (IS_ERR(dst)) {
+			xfrm_pol_put(policy);
+			return PTR_ERR(dst);
 		}
 
 		if (dst)
 			break;
 
+		nx = xfrm_tmpl_resolve(policy, fl, xfrm, family);
+
 		if (unlikely(nx<0)) {
 			err = nx;
 			if (err == -EAGAIN) {
@@ -1191,18 +805,7 @@
 
 				__set_task_state(tsk, TASK_INTERRUPTIBLE);
 				add_wait_queue(&km_waitq, &wait);
-				switch (family) {
-				case AF_INET:
-					err = xfrm4_tmpl_resolve(policy, fl, xfrm);
-					break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-				case AF_INET6:
-					err = xfrm6_tmpl_resolve(policy, fl, xfrm);
-					break;
-#endif
-				default:
-					err = -EINVAL;
-				}
+				err = xfrm_tmpl_resolve(policy, fl, xfrm, family);
 				if (err == -EAGAIN)
 					schedule();
 				__set_task_state(tsk, TASK_RUNNING);
@@ -1225,19 +828,8 @@
 		}
 
 		dst = &rt->u.dst;
-		switch (family) {
-		case AF_INET:
-			err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst);
-			break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			err = xfrm6_bundle_create(policy, xfrm, nx, fl, &dst);
-			break;
-#endif
-		default:
-			err = -EINVAL;
-		}
-			
+		err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst, family);
+
 		if (unlikely(err)) {
 			int i;
 			for (i=0; i<nx; i++)
@@ -1282,137 +874,39 @@
  */
 
 static inline int
-xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
-{
-	return	x->id.proto == tmpl->id.proto &&
-		(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
-		x->props.mode == tmpl->mode &&
-		(tmpl->aalgos & (1<<x->props.aalgo)) &&
-		(!x->props.mode || !tmpl->saddr.xfrm4_addr ||
-		 tmpl->saddr.xfrm4_addr == x->props.saddr.xfrm4_addr);
-}
-
-static inline int
-xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx)
-{
-	for (; idx < sp->len; idx++) {
-		if (xfrm_state_ok(tmpl, sp->xvec[idx]))
-			return ++idx;
-	}
-	return -1;
-}
-
-static void
-_decode_session4(struct sk_buff *skb, struct flowi *fl)
-{
-	struct iphdr *iph = skb->nh.iph;
-	u8 *xprth = skb->nh.raw + iph->ihl*4;
-
-	if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
-		switch (iph->protocol) {
-		case IPPROTO_UDP:
-		case IPPROTO_TCP:
-		case IPPROTO_SCTP:
-			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
-				u16 *ports = (u16 *)xprth;
-
-				fl->uli_u.ports.sport = ports[0];
-				fl->uli_u.ports.dport = ports[1];
-			}
-			break;
-
-		case IPPROTO_ESP:
-			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
-				u32 *ehdr = (u32 *)xprth;
-
-				fl->uli_u.spi = ehdr[0];
-			}
-			break;
-
-		case IPPROTO_AH:
-			if (pskb_may_pull(skb, xprth + 8 - skb->data)) {
-				u32 *ah_hdr = (u32*)xprth;
-
-				fl->uli_u.spi = ah_hdr[1];
-			}
-			break;
-
-		default:
-			fl->uli_u.spi = 0;
-			break;
-		};
-	} else {
-		memset(fl, 0, sizeof(struct flowi));
-	}
-	fl->proto = iph->protocol;
-	fl->fl4_dst = iph->daddr;
-	fl->fl4_src = iph->saddr;
-}
-
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-static inline int
-xfrm6_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, 
+	      unsigned short family)
 {
 	return	x->id.proto == tmpl->id.proto &&
 		(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
 		x->props.mode == tmpl->mode &&
 		(tmpl->aalgos & (1<<x->props.aalgo)) &&
-		(!x->props.mode || !ipv6_addr_any((struct in6_addr*)&x->props.saddr) ||
-		 !ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
+		!(x->props.mode && xfrm_state_addr_cmp(tmpl, x, family));
 }
 
 static inline int
-xfrm6_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx)
+xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx,
+	       unsigned short family)
 {
 	for (; idx < sp->len; idx++) {
-		if (xfrm6_state_ok(tmpl, sp->xvec[idx]))
+		if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
 			return ++idx;
 	}
 	return -1;
 }
 
-static inline void
-_decode_session6(struct sk_buff *skb, struct flowi *fl)
+static int
+_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
 {
-	u16 offset = sizeof(struct ipv6hdr);
-	struct ipv6hdr *hdr = skb->nh.ipv6h;
-	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-	u8 nexthdr = skb->nh.ipv6h->nexthdr;
-
-	fl->fl6_dst = &hdr->daddr;
-	fl->fl6_src = &hdr->saddr;
-
-	while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
-		switch (nexthdr) {
-		case NEXTHDR_ROUTING:
-		case NEXTHDR_HOP:
-		case NEXTHDR_DEST:
-			offset += ipv6_optlen(exthdr);
-			nexthdr = exthdr->nexthdr;
-			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-			break;
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
 
-		case IPPROTO_UDP:
-		case IPPROTO_TCP:
-		case IPPROTO_SCTP:
-			if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) {
-				u16 *ports = (u16 *)exthdr;
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
 
-				fl->uli_u.ports.sport = ports[0];
-				fl->uli_u.ports.dport = ports[1];
-			}
-			return;
-
-		/* XXX Why are there these headers? */
-		case IPPROTO_AH:
-		case IPPROTO_ESP:
-		default:
-			fl->uli_u.spi = 0;
-			return;
-		};
-	}
+	afinfo->decode_session(skb, fl);
+	xfrm_policy_put_afinfo(afinfo);
+	return 0;
 }
-#endif
 
 int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, 
 			unsigned short family)
@@ -1420,38 +914,15 @@
 	struct xfrm_policy *pol;
 	struct flowi fl;
 
-	switch (family) {
-	case AF_INET:
-		_decode_session4(skb, &fl);
-		break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		_decode_session6(skb, &fl);
-		break;
-#endif
-	default :
+	if (_decode_session(skb, &fl, family) < 0)
 		return 0;
-	}
 
 	/* First, check used SA against their selectors. */
 	if (skb->sp) {
 		int i;
 
 		for (i=skb->sp->len-1; i>=0; i--) {
-			int match;
-			switch (family) {
-			case AF_INET:
-				match = xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl);
-				break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-			case AF_INET6:
-				match = xfrm6_selector_match(&skb->sp->xvec[i]->sel, &fl);
-				break;
-#endif
-			default:
-				match = 0;
-			}
-			if (!match)
+			if (!xfrm_selector_match(&skb->sp->xvec[i]->sel, &fl, family))
 				return 0;
 		}
 	}
@@ -1483,20 +954,7 @@
 			 * are implied between each two transformations.
 			 */
 			for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
-				if (pol->xfrm_vec[i].optional)
-					continue;
-				switch (family) {
-				case AF_INET:
-					k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k);
-					break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-				case AF_INET6:
-					k = xfrm6_policy_ok(pol->xfrm_vec+i, sp, k);
-					break;
-#endif
-				default:
-					k = -1;
-				}
+				k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
 				if (k < 0)
 					goto reject;
 			}
@@ -1514,18 +972,8 @@
 {
 	struct flowi fl;
 
-	switch (family) {
-	case AF_INET:
-		_decode_session4(skb, &fl);
-		break;
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		_decode_session6(skb, &fl);
-		break;
-#endif
-	default:
+	if (_decode_session(skb, &fl, family) < 0)
 		return 0;
-	}
 
 	return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
 }
@@ -1603,20 +1051,6 @@
 	}
 }
 
-static inline int xfrm4_garbage_collect(void)
-{
-	__xfrm_garbage_collect();
-	return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static inline int xfrm6_garbage_collect(void)
-{
-	__xfrm_garbage_collect();
-	return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
-}
-#endif
-
 static int bundle_depends_on(struct dst_entry *dst, struct xfrm_state *x)
 {
 	do {
@@ -1660,29 +1094,6 @@
 	return 0;
 }
 
- 
-static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
-{
-	struct dst_entry *path = dst->path;
-
-	if (mtu < 68 + dst->header_len)
-		return;
-
-	path->ops->update_pmtu(path, mtu);
-}
-
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
-{
-	struct dst_entry *path = dst->path;
-
-	if (mtu >= 1280 && mtu < dst_pmtu(dst))
-		return;
-
-	path->ops->update_pmtu(path, mtu);
-}
-#endif
-
 /* Well... that's _TASK_. We need to scan through transformation
  * list and figure out what mss tcp should generate in order to
  * final datagram fit to mtu. Mama mia... :-)
@@ -1723,52 +1134,99 @@
 	return res + dst->header_len;
 }
 
-struct dst_ops xfrm4_dst_ops = {
-	.family =		AF_INET,
-	.protocol =		__constant_htons(ETH_P_IP),
-	.gc =			xfrm4_garbage_collect,
-	.check =		xfrm_dst_check,
-	.destroy =		xfrm_dst_destroy,
-	.negative_advice =	xfrm_negative_advice,
-	.link_failure =		xfrm_link_failure,
-	.update_pmtu =		xfrm4_update_pmtu,
-	.get_mss =		xfrm_get_mss,
-	.gc_thresh =		1024,
-	.entry_size =		sizeof(struct xfrm_dst),
-};
+int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
+{
+	int err = 0;
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	if (unlikely(afinfo->family >= NPROTO))
+		return -EAFNOSUPPORT;
+	write_lock(&xfrm_policy_afinfo_lock);
+	if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
+		err = -ENOBUFS;
+	else {
+		struct dst_ops *dst_ops = afinfo->dst_ops;
+		if (likely(dst_ops->kmem_cachep == NULL))
+			dst_ops->kmem_cachep = xfrm_dst_cache;
+		if (likely(dst_ops->check == NULL))
+			dst_ops->check = xfrm_dst_check;
+		if (likely(dst_ops->destroy == NULL))
+			dst_ops->destroy = xfrm_dst_destroy;
+		if (likely(dst_ops->negative_advice == NULL))
+			dst_ops->negative_advice = xfrm_negative_advice;
+		if (likely(dst_ops->link_failure == NULL))
+			dst_ops->link_failure = xfrm_link_failure;
+		if (likely(dst_ops->get_mss == NULL))
+			dst_ops->get_mss = xfrm_get_mss;
+		if (likely(afinfo->garbage_collect == NULL))
+			afinfo->garbage_collect = __xfrm_garbage_collect;
+		xfrm_policy_afinfo[afinfo->family] = afinfo;
+	}
+	write_unlock(&xfrm_policy_afinfo_lock);
+	return err;
+}
 
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-struct dst_ops xfrm6_dst_ops = {
-	.family =		AF_INET6,
-	.protocol =		__constant_htons(ETH_P_IPV6),
-	.gc =			xfrm6_garbage_collect,
-	.check =		xfrm_dst_check,
-	.destroy =		xfrm_dst_destroy,
-	.negative_advice =	xfrm_negative_advice,
-	.link_failure =		xfrm_link_failure,
-	.update_pmtu =		xfrm6_update_pmtu,
-	.get_mss =		xfrm_get_mss,
-	.gc_thresh =		1024,
-	.entry_size =		sizeof(struct xfrm_dst),
-};
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
+{
+	int err = 0;
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	if (unlikely(afinfo->family >= NPROTO))
+		return -EAFNOSUPPORT;
+	write_lock(&xfrm_policy_afinfo_lock);
+	if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) {
+		if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo))
+			err = -EINVAL;
+		else {
+			struct dst_ops *dst_ops = afinfo->dst_ops;
+			xfrm_policy_afinfo[afinfo->family] = NULL;
+			dst_ops->kmem_cachep = NULL;
+			dst_ops->check = NULL;
+			dst_ops->destroy = NULL;
+			dst_ops->negative_advice = NULL;
+			dst_ops->link_failure = NULL;
+			dst_ops->get_mss = NULL;
+			afinfo->garbage_collect = NULL;
+		}
+	}
+	write_unlock(&xfrm_policy_afinfo_lock);
+	return err;
+}
 
-void __init xfrm_init(void)
+struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
 {
-	xfrm4_dst_ops.kmem_cachep = kmem_cache_create("xfrm4_dst_cache",
-						      sizeof(struct xfrm_dst),
-						      0, SLAB_HWCACHE_ALIGN,
-						      NULL, NULL);
-
-	if (!xfrm4_dst_ops.kmem_cachep)
-		panic("IP: failed to allocate xfrm4_dst_cache\n");
-
-#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-	xfrm6_dst_ops.kmem_cachep = xfrm4_dst_ops.kmem_cachep;
-#endif
+	struct xfrm_policy_afinfo *afinfo;
+	if (unlikely(family >= NPROTO))
+		return NULL;
+	read_lock(&xfrm_policy_afinfo_lock);
+	afinfo = xfrm_policy_afinfo[family];
+	if (likely(afinfo != NULL))
+		read_lock(&afinfo->lock);
+	read_unlock(&xfrm_policy_afinfo_lock);
+	return afinfo;
+}
 
-	flow_cache_init();
+void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
+{
+	if (unlikely(afinfo == NULL))
+		return;
+	read_unlock(&afinfo->lock);
+}
+
+void __init xfrm_policy_init(void)
+{
+	xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
+					   sizeof(struct xfrm_dst),
+					   0, SLAB_HWCACHE_ALIGN,
+					   NULL, NULL);
+	if (!xfrm_dst_cache)
+		panic("XFRM: failed to allocate xfrm_dst_cache\n");
+}
+
+void __init xfrm_init(void)
+{
 	xfrm_state_init();
-	xfrm_input_init();
+	flow_cache_init();
+	xfrm_policy_init();
 }
 
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm_state.c linux-2.5.65-bk5/net/ipv4/xfrm_state.c
--- linux-2.5.65-bk4/net/ipv4/xfrm_state.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/xfrm_state.c	Mon Mar 31 12:44:34 2003
@@ -1,15 +1,19 @@
-/* Changes
+/*
+ * xfrm_state.c
  *
- *	Mitsuru KANDA @USAGI       : IPv6 Support 
- * 	Kazunori MIYAZAWA @USAGI   :
- * 	Kunihiro Ishiguro          :
+ * Changes:
+ *	Mitsuru KANDA @USAGI
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	Kunihiro Ishiguro
+ * 		IPv6 support
+ * 	YOSHIFUJI Hideaki @USAGI
+ * 		Split up af-specific functions
  * 	
  */
 
 #include <net/xfrm.h>
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
-#include <net/ipv6.h>
 
 /* Each xfrm_state may be linked to two tables:
 
@@ -20,8 +24,6 @@
 
 static spinlock_t xfrm_state_lock = SPIN_LOCK_UNLOCKED;
 
-#define XFRM_DST_HSIZE		1024
-
 /* Hash table to find appropriate SA towards given target (endpoint
  * of tunnel or destination of transport mode) allowed by selector.
  *
@@ -33,7 +35,8 @@
 
 DECLARE_WAIT_QUEUE_HEAD(km_waitq);
 
-#define ACQ_EXPIRES 30
+static rwlock_t xfrm_state_afinfo_lock = RW_LOCK_UNLOCKED;
+static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
 
 static void __xfrm_state_delete(struct xfrm_state *x);
 
@@ -214,138 +217,37 @@
 	wake_up(&km_waitq);
 }
 
-struct xfrm_state *
-xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-		 struct xfrm_policy *pol, int *err)
-{
-	unsigned h = ntohl(daddr);
-	struct xfrm_state *x;
-	int acquire_in_progress = 0;
-	int error = 0;
-	struct xfrm_state *best = NULL;
-
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
-		if (x->props.family == AF_INET &&
-		    daddr == x->id.daddr.xfrm4_addr &&
-		    x->props.reqid == tmpl->reqid &&
-		    (saddr == x->props.saddr.xfrm4_addr || !saddr || !x->props.saddr.xfrm4_addr) &&
-		    tmpl->mode == x->props.mode &&
-		    tmpl->id.proto == x->id.proto) {
-			/* Resolution logic:
-			   1. There is a valid state with matching selector.
-			      Done.
-			   2. Valid state with inappropriate selector. Skip.
-
-			   Entering area of "sysdeps".
-
-			   3. If state is not valid, selector is temporary,
-			      it selects only session which triggered
-			      previous resolution. Key manager will do
-			      something to install a state with proper
-			      selector.
-			 */
-			if (x->km.state == XFRM_STATE_VALID) {
-				if (!xfrm4_selector_match(&x->sel, fl))
-					continue;
-				if (!best ||
-				    best->km.dying > x->km.dying ||
-				    (best->km.dying == x->km.dying &&
-				     best->curlft.add_time < x->curlft.add_time))
-					best = x;
-			} else if (x->km.state == XFRM_STATE_ACQ) {
-				acquire_in_progress = 1;
-			} else if (x->km.state == XFRM_STATE_ERROR ||
-				   x->km.state == XFRM_STATE_EXPIRED) {
-				if (xfrm4_selector_match(&x->sel, fl))
-					error = 1;
-			}
-		}
-	}
-
-	if (best) {
-		atomic_inc(&best->refcnt);
-		spin_unlock_bh(&xfrm_state_lock);
-		return best;
-	}
-
-	x = NULL;
-	if (!error && !acquire_in_progress &&
-	    ((x = xfrm_state_alloc()) != NULL)) {
-		/* Initialize temporary selector matching only
-		 * to current session. */
-
-		x->sel.daddr.xfrm4_addr = fl->fl4_dst;
-		x->sel.daddr.xfrm4_mask = ~0;
-		x->sel.saddr.xfrm4_addr = fl->fl4_src;
-		x->sel.saddr.xfrm4_mask = ~0;
-		x->sel.dport = fl->uli_u.ports.dport;
-		x->sel.dport_mask = ~0;
-		x->sel.sport = fl->uli_u.ports.sport;
-		x->sel.sport_mask = ~0;
-		x->sel.prefixlen_d = 32;
-		x->sel.prefixlen_s = 32;
-		x->sel.proto = fl->proto;
-		x->sel.ifindex = fl->oif;
-		x->id = tmpl->id;
-		if (x->id.daddr.xfrm4_addr == 0)
-			x->id.daddr.xfrm4_addr = daddr;
-		x->props.family = AF_INET;
-		x->props.saddr = tmpl->saddr;
-		if (x->props.saddr.xfrm4_addr == 0)
-			x->props.saddr.xfrm4_addr = saddr;
-		x->props.mode = tmpl->mode;
-		x->props.reqid = tmpl->reqid;
-		x->props.family = AF_INET;
-
-		if (km_query(x, tmpl, pol) == 0) {
-			x->km.state = XFRM_STATE_ACQ;
-			list_add_tail(&x->bydst, xfrm_state_bydst+h);
-			atomic_inc(&x->refcnt);
-			if (x->id.spi) {
-				h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
-				h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
-				list_add(&x->byspi, xfrm_state_byspi+h);
-				atomic_inc(&x->refcnt);
-			}
-			x->lft.hard_add_expires_seconds = ACQ_EXPIRES;
-			atomic_inc(&x->refcnt);
-			mod_timer(&x->timer, ACQ_EXPIRES*HZ);
-		} else {
-			x->km.state = XFRM_STATE_DEAD;
-			xfrm_state_put(x);
-			x = NULL;
-			error = 1;
-		}
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	if (!x)
-		*err = acquire_in_progress ? -EAGAIN :
-			(error ? -ESRCH : -ENOMEM);
-	return x;
+static int
+xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
+		  struct xfrm_tmpl *tmpl,
+		  xfrm_address_t *daddr, xfrm_address_t *saddr,
+		  unsigned short family)
+{
+	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
+	if (!afinfo)
+		return -1;
+	afinfo->init_tempsel(x, fl, tmpl, daddr, saddr);
+	xfrm_state_put_afinfo(afinfo);
+	return 0;
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 struct xfrm_state *
-xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-		struct xfrm_policy *pol, int *err)
+xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 
+		struct flowi *fl, struct xfrm_tmpl *tmpl,
+		struct xfrm_policy *pol, int *err,
+		unsigned short family)
 {
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
+	unsigned h = xfrm_dst_hash(daddr, family);
 	struct xfrm_state *x;
 	int acquire_in_progress = 0;
 	int error = 0;
 	struct xfrm_state *best = NULL;
 
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
-
 	spin_lock_bh(&xfrm_state_lock);
 	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
-		if (x->props.family == AF_INET6&&
-		    !ipv6_addr_cmp(daddr, (struct in6_addr *)&x->id.daddr) &&
+		if (x->props.family == family &&
 		    x->props.reqid == tmpl->reqid &&
-		    (!ipv6_addr_cmp(saddr, (struct in6_addr *)&x->props.saddr)|| ipv6_addr_any(saddr)) &&
+		    xfrm_state_addr_check(x, daddr, saddr, family) &&
 		    tmpl->mode == x->props.mode &&
 		    tmpl->id.proto == x->id.proto) {
 			/* Resolution logic:
@@ -362,7 +264,7 @@
 			      selector.
 			 */
 			if (x->km.state == XFRM_STATE_VALID) {
-				if (!xfrm6_selector_match(&x->sel, fl))
+				if (!xfrm_selector_match(&x->sel, fl, family))
 					continue;
 				if (!best ||
 				    best->km.dying > x->km.dying ||
@@ -373,7 +275,7 @@
 				acquire_in_progress = 1;
 			} else if (x->km.state == XFRM_STATE_ERROR ||
 				   x->km.state == XFRM_STATE_EXPIRED) {
-				if (xfrm6_selector_match(&x->sel, fl))
+				if (xfrm_selector_match(&x->sel, fl, family))
 					error = 1;
 			}
 		}
@@ -384,45 +286,26 @@
 		spin_unlock_bh(&xfrm_state_lock);
 		return best;
 	}
+
 	x = NULL;
 	if (!error && !acquire_in_progress &&
 	    ((x = xfrm_state_alloc()) != NULL)) {
 		/* Initialize temporary selector matching only
 		 * to current session. */
-		memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr));
-		memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr));
-		x->sel.dport = fl->uli_u.ports.dport;
-		x->sel.dport_mask = ~0;
-		x->sel.sport = fl->uli_u.ports.sport;
-		x->sel.sport_mask = ~0;
-		x->sel.prefixlen_d = 128;
-		x->sel.prefixlen_s = 128;
-		x->sel.proto = fl->proto;
-		x->sel.ifindex = fl->oif;
-		x->id = tmpl->id;
-		if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
-			memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
-		memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
-		if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
-			memcpy(&x->props.saddr, &saddr, sizeof(x->sel.saddr));
-		x->props.mode = tmpl->mode;
-		x->props.reqid = tmpl->reqid;
-		x->props.family = AF_INET6;
+		xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
 
 		if (km_query(x, tmpl, pol) == 0) {
 			x->km.state = XFRM_STATE_ACQ;
 			list_add_tail(&x->bydst, xfrm_state_bydst+h);
 			atomic_inc(&x->refcnt);
 			if (x->id.spi) {
-				struct in6_addr *addr = (struct in6_addr*)&x->id.daddr;
-				h = ntohl((addr->s6_addr32[2]^addr->s6_addr32[3])^x->id.spi^x->id.proto);
-				h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+				h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
 				list_add(&x->byspi, xfrm_state_byspi+h);
 				atomic_inc(&x->refcnt);
 			}
-			x->lft.hard_add_expires_seconds = ACQ_EXPIRES;
+			x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
 			atomic_inc(&x->refcnt);
-			mod_timer(&x->timer, ACQ_EXPIRES*HZ);
+			mod_timer(&x->timer, XFRM_ACQ_EXPIRES*HZ);
 		} else {
 			x->km.state = XFRM_STATE_DEAD;
 			xfrm_state_put(x);
@@ -436,36 +319,17 @@
 			(error ? -ESRCH : -ENOMEM);
 	return x;
 }
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
 
 void xfrm_state_insert(struct xfrm_state *x)
 {
-	unsigned h = 0;
-
-	switch (x->props.family) {
-	case AF_INET:
-		h = ntohl(x->id.daddr.xfrm4_addr);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]);
-		break;
-#endif
-	default:
-		return;
-	}
-
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+	unsigned h = xfrm_dst_hash(&x->id.daddr, x->props.family);
 
 	spin_lock_bh(&xfrm_state_lock);
 	list_add(&x->bydst, xfrm_state_bydst+h);
 	atomic_inc(&x->refcnt);
 
-	if (x->props.family == AF_INET)
-		h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
-	else
-		h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
-	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+	h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
+
 	list_add(&x->byspi, xfrm_state_byspi+h);
 	atomic_inc(&x->refcnt);
 
@@ -487,7 +351,7 @@
 	if (x->curlft.bytes >= x->lft.hard_byte_limit ||
 	    x->curlft.packets >= x->lft.hard_packet_limit) {
 		km_expired(x);
-		if (!mod_timer(&x->timer, jiffies + ACQ_EXPIRES*HZ))
+		if (!mod_timer(&x->timer, jiffies + XFRM_ACQ_EXPIRES*HZ))
 			atomic_inc(&x->refcnt);
 		return -EINVAL;
 	}
@@ -512,158 +376,37 @@
 }
 
 struct xfrm_state *
-xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto)
+xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
+		  unsigned short family)
 {
-	unsigned h = ntohl(daddr^spi^proto);
 	struct xfrm_state *x;
-
-	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
+	if (!afinfo)
+		return NULL;
 
 	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
-		if (x->props.family == AF_INET &&
-		    spi == x->id.spi &&
-		    daddr == x->id.daddr.xfrm4_addr &&
-		    proto == x->id.proto) {
-			atomic_inc(&x->refcnt);
-			spin_unlock_bh(&xfrm_state_lock);
-			return x;
-		}
-	}
+	x = afinfo->state_lookup(daddr, spi, proto);
 	spin_unlock_bh(&xfrm_state_lock);
-	return NULL;
+	xfrm_state_put_afinfo(afinfo);
+	return x;
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 struct xfrm_state *
-xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto)
+xfrm_find_acq(u8 mode, u16 reqid, u8 proto, 
+	      xfrm_address_t *daddr, xfrm_address_t *saddr, 
+	      int create, unsigned short family)
 {
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto);
 	struct xfrm_state *x;
-
-	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
+	if (!afinfo)
+		return NULL;
 
 	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
-		if (x->props.family == AF_INET6 &&
-		    spi == x->id.spi &&
-		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
-		    proto == x->id.proto) {
-			atomic_inc(&x->refcnt);
-			spin_unlock_bh(&xfrm_state_lock);
-			return x;
-		}
-	}
+	x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create);
 	spin_unlock_bh(&xfrm_state_lock);
-	return NULL;
-}
-#endif
-
-struct xfrm_state *
-xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
-{
-	struct xfrm_state *x, *x0;
-	unsigned h = ntohl(daddr);
-
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
-	x0 = NULL;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
-		if (x->props.family == AF_INET &&
-		    daddr == x->id.daddr.xfrm4_addr &&
-		    mode == x->props.mode &&
-		    proto == x->id.proto &&
-		    saddr == x->props.saddr.xfrm4_addr &&
-		    reqid == x->props.reqid &&
-		    x->km.state == XFRM_STATE_ACQ) {
-			    if (!x0)
-				    x0 = x;
-			    if (x->id.spi)
-				    continue;
-			    x0 = x;
-			    break;
-		    }
-	}
-	if (x0) {
-		atomic_inc(&x0->refcnt);
-	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
-		x0->sel.daddr.xfrm4_addr = daddr;
-		x0->sel.daddr.xfrm4_mask = ~0;
-		x0->sel.saddr.xfrm4_addr = saddr;
-		x0->sel.saddr.xfrm4_mask = ~0;
-		x0->sel.prefixlen_d = 32;
-		x0->sel.prefixlen_s = 32;
-		x0->props.saddr.xfrm4_addr = saddr;
-		x0->km.state = XFRM_STATE_ACQ;
-		x0->id.daddr.xfrm4_addr = daddr;
-		x0->id.proto = proto;
-		x0->props.mode = mode;
-		x0->props.reqid = reqid;
-		x0->props.family = AF_INET;
-		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
-		atomic_inc(&x0->refcnt);
-		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
-		atomic_inc(&x0->refcnt);
-		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
-		wake_up(&km_waitq);
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	return x0;
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-struct xfrm_state *
-xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create)
-{
-	struct xfrm_state *x, *x0;
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
-
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
-	x0 = NULL;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
-		if (x->props.family == AF_INET6 &&
-		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
-		    mode == x->props.mode &&
-		    proto == x->id.proto &&
-		    !ipv6_addr_cmp(saddr, (struct in6_addr *)x->props.saddr.a6) &&
-		    reqid == x->props.reqid &&
-		    x->km.state == XFRM_STATE_ACQ) {
-			    if (!x0)
-				    x0 = x;
-			    if (x->id.spi)
-				    continue;
-			    x0 = x;
-			    break;
-		    }
-	}
-	if (x0) {
-		atomic_inc(&x0->refcnt);
-	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
-		memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
-		memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
-		x0->sel.prefixlen_d = 128;
-		x0->sel.prefixlen_s = 128;
-		memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
-		x0->km.state = XFRM_STATE_ACQ;
-		memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
-		x0->id.proto = proto;
-		x0->props.family = AF_INET6;
-		x0->props.mode = mode;
-		x0->props.reqid = reqid;
-		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
-		atomic_inc(&x0->refcnt);
-		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
-		atomic_inc(&x0->refcnt);
-		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
-		wake_up(&km_waitq);
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	return x0;
+	xfrm_state_put_afinfo(afinfo);
+	return x;
 }
-#endif
 
 /* Silly enough, but I'm lazy to build resolution list */
 
@@ -697,18 +440,7 @@
 		return;
 
 	if (minspi == maxspi) {
-		switch(x->props.family) {
-		case AF_INET:
-			x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
-			break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
-			break;
-#endif
-		default:
-			x0 = NULL;
-		}
+		x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family);
 		if (x0) {
 			xfrm_state_put(x0);
 			return;
@@ -720,18 +452,7 @@
 		maxspi = ntohl(maxspi);
 		for (h=0; h<maxspi-minspi+1; h++) {
 			spi = minspi + net_random()%(maxspi-minspi+1);
-			switch(x->props.family) {
-			case AF_INET:
-				x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
-				break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-			case AF_INET6:
-				x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
-				break;
-#endif
-			default:
-				x0 = NULL;
-			}
+			x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family);
 			if (x0 == NULL)
 				break;
 			xfrm_state_put(x0);
@@ -740,19 +461,7 @@
 	}
 	if (x->id.spi) {
 		spin_lock_bh(&xfrm_state_lock);
-		switch(x->props.family) {
-		case AF_INET:
-			h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
-			break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
-			break;
-#endif
-		default:
-			h = 0;	/* XXX */
-		}
-		h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+		h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
 		list_add(&x->byspi, xfrm_state_byspi+h);
 		atomic_inc(&x->refcnt);
 		spin_unlock_bh(&xfrm_state_lock);
@@ -845,18 +554,7 @@
 
 	for (i=0; i<n; i++) {
 		int match;
-		switch(x[i]->props.family) {
-		case AF_INET:
-			match = xfrm4_selector_match(&x[i]->sel, fl);
-			break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			match = xfrm6_selector_match(&x[i]->sel, fl);
-			break;
-#endif
-		default:
-			match = 0;
-		}
+		match = xfrm_selector_match(&x[i]->sel, fl, x[i]->props.family);
 		if (!match)
 			return -EINVAL;
 	}
@@ -958,6 +656,66 @@
 	return 0;
 }
 
+int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
+{
+	int err = 0;
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	if (unlikely(afinfo->family >= NPROTO))
+		return -EAFNOSUPPORT;
+	write_lock(&xfrm_state_afinfo_lock);
+	if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
+		err = -ENOBUFS;
+	else {
+		afinfo->state_bydst = xfrm_state_bydst;
+		afinfo->state_byspi = xfrm_state_byspi;
+		xfrm_state_afinfo[afinfo->family] = afinfo;
+	}
+	write_unlock(&xfrm_state_afinfo_lock);
+	return err;
+}
+
+int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
+{
+	int err = 0;
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	if (unlikely(afinfo->family >= NPROTO))
+		return -EAFNOSUPPORT;
+	write_lock(&xfrm_state_afinfo_lock);
+	if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
+		if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
+			err = -EINVAL;
+		else {
+			xfrm_state_afinfo[afinfo->family] = NULL;
+			afinfo->state_byspi = NULL;
+			afinfo->state_bydst = NULL;
+		}
+	}
+	write_unlock(&xfrm_state_afinfo_lock);
+	return err;
+}
+
+struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
+{
+	struct xfrm_state_afinfo *afinfo;
+	if (unlikely(family >= NPROTO))
+		return NULL;
+	read_lock(&xfrm_state_afinfo_lock);
+	afinfo = xfrm_state_afinfo[family];
+	if (likely(afinfo != NULL))
+		read_lock(&afinfo->lock);
+	read_unlock(&xfrm_state_afinfo_lock);
+	return afinfo;
+}
+
+void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+{
+	if (unlikely(afinfo == NULL))
+		return;
+	read_unlock(&afinfo->lock);
+}
+
 void __init xfrm_state_init(void)
 {
 	int i;
diff -urN linux-2.5.65-bk4/net/ipv4/xfrm_user.c linux-2.5.65-bk5/net/ipv4/xfrm_user.c
--- linux-2.5.65-bk4/net/ipv4/xfrm_user.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv4/xfrm_user.c	Mon Mar 31 12:44:34 2003
@@ -2,11 +2,11 @@
  *
  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
  *
- * Changes
- *
- *	Mitsuru KANDA @USAGI       : IPv6 Support 
- * 	Kazunori MIYAZAWA @USAGI   :
- * 	Kunihiro Ishiguro          :
+ * Changes:
+ *	Mitsuru KANDA @USAGI
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	Kunihiro Ishiguro
+ * 		IPv6 support
  * 	
  */
 
@@ -24,9 +24,6 @@
 #include <linux/ipsec.h>
 #include <linux/init.h>
 #include <linux/security.h>
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-#include <linux/in6.h>
-#endif
 #include <net/sock.h>
 #include <net/xfrm.h>
 
@@ -191,19 +188,7 @@
 		goto error;
 
 	err = -ENOENT;
-	switch (x->props.family) {
-	case AF_INET:
-		x->type = xfrm_get_type(x->id.proto);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		x->type = xfrm6_get_type(x->id.proto);
-		break;
-#endif
-	default:
-		x->type = NULL;
-		break;
-	}
+	x->type = xfrm_get_type(x->id.proto, x->props.family);
 	if (x->type == NULL)
 		goto error;
 
@@ -238,21 +223,7 @@
 	if (!x)
 		return err;
 
-	switch (x->props.family) {
-	case AF_INET:
-		x1 = xfrm4_state_lookup(x->props.saddr.xfrm4_addr,
-					x->id.spi, x->id.proto);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		x1 = xfrm6_state_lookup((struct in6_addr*)x->props.saddr.a6,
-					x->id.spi, x->id.proto);
-		break;
-#endif
-	default:
-		x1 = NULL;
-		break;
-	}
+	x1 = xfrm_state_lookup(&x->props.saddr, x->id.spi, x->id.proto, x->props.family);
 	if (x1) {
 		xfrm_state_put(x);
 		xfrm_state_put(x1);
@@ -269,19 +240,7 @@
 	struct xfrm_state *x;
 	struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
 
-	switch (p->family) {
-	case AF_INET:
-		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		x = xfrm6_state_lookup((struct in6_addr*)p->saddr.a6, p->spi, p->proto);
-		break;
-#endif
-	default:
-		x = NULL;
-		break;
-	}
+	x = xfrm_state_lookup(&p->saddr, p->spi, p->proto, p->family);
 	if (x == NULL)
 		return -ESRCH;
 
@@ -399,19 +358,7 @@
 	struct sk_buff *resp_skb;
 	int err;
 
-	switch (p->family) {
-	case AF_INET:
-		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		x = xfrm6_state_lookup((struct in6_addr*)p->saddr.a6, p->spi, p->proto);
-		break;
-#endif
-	default:
-		x = NULL;
-		break;
-	}
+	x = xfrm_state_lookup(&p->saddr, p->spi, p->proto, p->family);
 	err = -ESRCH;
 	if (x == NULL)
 		goto out_noput;
@@ -462,23 +409,10 @@
 	err = verify_userspi_info(p);
 	if (err)
 		goto out_noput;
-	switch (p->info.family) {
-	case AF_INET:
-		x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
-				  p->info.sel.daddr.xfrm4_addr,
-				  p->info.sel.saddr.xfrm4_addr, 1);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		x = xfrm6_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
-				   (struct in6_addr*)p->info.sel.daddr.a6,
-				   (struct in6_addr*)p->info.sel.saddr.a6, 1);
-		break;
-#endif
-	default:
-		x = NULL;
-		break;
-	}
+	x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
+			  &p->info.sel.daddr,
+			  &p->info.sel.saddr, 1,
+			  p->info.family);
 	err = -ENOENT;
 	if (x == NULL)
 		goto out_noput;
@@ -1086,10 +1020,26 @@
 	struct xfrm_policy *xp;
 	int nr;
 
-	if (opt != IP_XFRM_POLICY) {
-		*dir = -EOPNOTSUPP;
+	switch (family) {
+	case AF_INET:
+		if (opt != IP_XFRM_POLICY) {
+			*dir = -EOPNOTSUPP;
+			return NULL;
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		if (opt != IPV6_XFRM_POLICY) {
+			*dir = -EOPNOTSUPP;
+			return NULL;
+		}
+		break;
+#endif
+	default:
+		*dir = -EINVAL;
 		return NULL;
 	}
+
 	*dir = -EINVAL;
 
 	if (len < sizeof(*p) ||
diff -urN linux-2.5.65-bk4/net/ipv6/Makefile linux-2.5.65-bk5/net/ipv6/Makefile
--- linux-2.5.65-bk4/net/ipv6/Makefile	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/Makefile	Mon Mar 31 12:44:34 2003
@@ -8,7 +8,8 @@
 		route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
 		protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
-		ip6_flowlabel.o ipv6_syms.o
+		ip6_flowlabel.o ipv6_syms.o \
+		xfrm6_policy.o xfrm6_state.o xfrm6_input.o
 
 obj-$(CONFIG_INET6_AH) += ah6.o
 obj-$(CONFIG_INET6_ESP) += esp6.o
diff -urN linux-2.5.65-bk4/net/ipv6/addrconf.c linux-2.5.65-bk5/net/ipv6/addrconf.c
--- linux-2.5.65-bk4/net/ipv6/addrconf.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/addrconf.c	Mon Mar 31 12:44:34 2003
@@ -97,6 +97,8 @@
 static void ipv6_regen_rndid(unsigned long data);
 
 static int desync_factor = MAX_DESYNC_FACTOR * HZ;
+static struct crypto_tfm *md5_tfm;
+static spinlock_t md5_tfm_lock = SPIN_LOCK_UNLOCKED;
 #endif
 
 static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -172,7 +174,7 @@
 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
 
-int ipv6_addr_type(struct in6_addr *addr)
+int ipv6_addr_type(const struct in6_addr *addr)
 {
 	int type;
 	u32 st;
@@ -426,8 +428,7 @@
 	}
 	for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
 		ipv6_addr_prefix(&addr, &ifa->addr, ifa->prefix_len);
-		if (addr.s6_addr32[0] == 0 && addr.s6_addr32[1] == 0 &&
-		    addr.s6_addr32[2] == 0 && addr.s6_addr32[3] == 0)
+		if (ipv6_addr_any(&addr))
 			continue;
 		if (idev->cnf.forwarding)
 			ipv6_dev_ac_inc(idev->dev, &addr);
@@ -486,7 +487,7 @@
 /* On success it returns ifp with increased reference count */
 
 static struct inet6_ifaddr *
-ipv6_add_addr(struct inet6_dev *idev, struct in6_addr *addr, int pfxlen,
+ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 	      int scope, unsigned flags)
 {
 	struct inet6_ifaddr *ifa;
@@ -1046,7 +1047,6 @@
 	struct net_device *dev;
 	u8 eui64[8];
 	u8 digest[16];
-	struct crypto_tfm *tfm;
 	struct scatterlist sg[2];
 
 	sg[0].page = virt_to_page(idev->entropy);
@@ -1068,18 +1068,16 @@
 		get_random_bytes(eui64, sizeof(eui64));
 	}
 regen:
-	tfm = crypto_alloc_tfm("md5", 0);
-	if (tfm == NULL) {
-		if (net_ratelimit())
-			printk(KERN_WARNING
-				"failed to load transform for md5\n");
+	spin_lock(&md5_tfm_lock);
+	if (unlikely(md5_tfm == NULL)) {
+		spin_unlock(&md5_tfm_lock);
 		in6_dev_put(idev);
 		return -1;
 	}
-	crypto_digest_init(tfm);
-	crypto_digest_update(tfm, sg, 2);
-	crypto_digest_final(tfm, digest);
-	crypto_free_tfm(tfm);
+	crypto_digest_init(md5_tfm);
+	crypto_digest_update(md5_tfm, sg, 2);
+	crypto_digest_final(md5_tfm, digest);
+	spin_unlock(&md5_tfm_lock);
 
 	memcpy(idev->rndid, &digest[0], 8);
 	idev->rndid[0] &= ~0x02;
@@ -1107,6 +1105,9 @@
 			goto regen;
 	}
 	
+	idev->regen_timer.expires = jiffies +
+					idev->cnf.temp_prefered_lft * HZ - 
+					idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
 	if (time_before(idev->regen_timer.expires, jiffies)) {
 		idev->regen_timer.expires = 0;
 		printk(KERN_WARNING
@@ -1646,7 +1647,6 @@
 
 static void init_loopback(struct net_device *dev)
 {
-	struct in6_addr addr;
 	struct inet6_dev  *idev;
 	struct inet6_ifaddr * ifp;
 
@@ -1654,15 +1654,12 @@
 
 	ASSERT_RTNL();
 
-	memset(&addr, 0, sizeof(struct in6_addr));
-	addr.s6_addr[15] = 1;
-
 	if ((idev = ipv6_find_idev(dev)) == NULL) {
 		printk(KERN_DEBUG "init loopback: add_dev failed\n");
 		return;
 	}
 
-	ifp = ipv6_add_addr(idev, &addr, 128, IFA_HOST, IFA_F_PERMANENT);
+	ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT);
 	if (ifp) {
 		spin_lock_bh(&ifp->lock);
 		ifp->flags &= ~IFA_F_TENTATIVE;
@@ -2034,8 +2031,7 @@
 		struct in6_addr addr;
 
 		ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
-		if (addr.s6_addr32[0] || addr.s6_addr32[1] ||
-		    addr.s6_addr32[2] || addr.s6_addr32[3])
+		if (!ipv6_addr_any(&addr))
 			ipv6_dev_ac_inc(ifp->idev->dev, &addr);
 	}
 }
@@ -2372,8 +2368,7 @@
 			struct in6_addr addr;
 
 			ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
-			if (addr.s6_addr32[0] || addr.s6_addr32[1] ||
-			    addr.s6_addr32[2] || addr.s6_addr32[3])
+			if (!ipv6_addr_any(&addr))
 				ipv6_dev_ac_dec(ifp->idev->dev, &addr);
 		}
 		if (!ipv6_chk_addr(&ifp->addr, NULL))
@@ -2654,7 +2649,16 @@
 {
 #ifdef MODULE
 	struct net_device *dev;
+#endif
+
+#ifdef CONFIG_IPV6_PRIVACY
+	md5_tfm = crypto_alloc_tfm("md5", 0);
+	if (unlikely(md5_tfm == NULL))
+		printk(KERN_WARNING
+			"failed to load transform for md5\n");
+#endif
 
+#ifdef MODULE
 	/* This takes sense only during module load. */
 	rtnl_lock();
 	for (dev = dev_base; dev; dev = dev->next) {
@@ -2739,6 +2743,13 @@
 
 	rtnl_unlock();
 
+#ifdef CONFIG_IPV6_PRIVACY
+	if (likely(md5_tfm != NULL)) {
+		crypto_free_tfm(md5_tfm);
+		md5_tfm = NULL;
+	}
+#endif
+
 #ifdef CONFIG_PROC_FS
 	proc_net_remove("if_inet6");
 #endif
diff -urN linux-2.5.65-bk4/net/ipv6/af_inet6.c linux-2.5.65-bk5/net/ipv6/af_inet6.c
--- linux-2.5.65-bk4/net/ipv6/af_inet6.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/af_inet6.c	Mon Mar 31 12:44:34 2003
@@ -799,6 +799,13 @@
 	addrconf_init();
 	sit_init();
 
+	/* Init v6 extention headers. */
+	ipv6_hopopts_init();
+	ipv6_rthdr_init();
+	ipv6_frag_init();
+	ipv6_nodata_init();
+	ipv6_destopt_init();
+
 	/* Init v6 transport protocols. */
 	udpv6_init();
 	tcpv6_init();
diff -urN linux-2.5.65-bk4/net/ipv6/ah6.c linux-2.5.65-bk5/net/ipv6/ah6.c
--- linux-2.5.65-bk4/net/ipv6/ah6.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/ah6.c	Mon Mar 31 12:44:34 2003
@@ -228,7 +228,7 @@
 	    type != ICMPV6_PKT_TOOBIG)
 		return;
 
-	x = xfrm6_state_lookup(&iph->daddr, ah->spi, IPPROTO_AH);
+	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6);
 	if (!x)
 		return;
 
@@ -336,14 +336,14 @@
 {
 	SET_MODULE_OWNER(&ah6_type);
 
-	if (xfrm6_register_type(&ah6_type) < 0) {
+	if (xfrm_register_type(&ah6_type, AF_INET6) < 0) {
 		printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
 
 	if (inet6_add_protocol(&ah6_protocol, IPPROTO_AH) < 0) {
 		printk(KERN_INFO "ipv6 ah init: can't add protocol\n");
-		xfrm6_unregister_type(&ah6_type);
+		xfrm_unregister_type(&ah6_type, AF_INET6);
 		return -EAGAIN;
 	}
 
@@ -355,7 +355,7 @@
 	if (inet6_del_protocol(&ah6_protocol, IPPROTO_AH) < 0)
 		printk(KERN_INFO "ipv6 ah close: can't remove protocol\n");
 
-	if (xfrm6_unregister_type(&ah6_type) < 0)
+	if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0)
 		printk(KERN_INFO "ipv6 ah close: can't remove xfrm type\n");
 
 }
diff -urN linux-2.5.65-bk4/net/ipv6/esp6.c linux-2.5.65-bk5/net/ipv6/esp6.c
--- linux-2.5.65-bk4/net/ipv6/esp6.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/esp6.c	Mon Mar 31 12:44:34 2003
@@ -377,7 +377,7 @@
 	    type != ICMPV6_PKT_TOOBIG)
 		return;
 
-	x = xfrm6_state_lookup(&iph->daddr, esph->spi, IPPROTO_ESP);
+	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/"
@@ -504,13 +504,13 @@
 int __init esp6_init(void)
 {
 	SET_MODULE_OWNER(&esp6_type);
-	if (xfrm6_register_type(&esp6_type) < 0) {
+	if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
 		printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
 	if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) {
 		printk(KERN_INFO "ipv6 esp init: can't add protocol\n");
-		xfrm6_unregister_type(&esp6_type);
+		xfrm_unregister_type(&esp6_type, AF_INET6);
 		return -EAGAIN;
 	}
 
@@ -521,7 +521,7 @@
 {
 	if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0)
 		printk(KERN_INFO "ipv6 esp close: can't remove protocol\n");
-	if (xfrm6_unregister_type(&esp6_type) < 0)
+	if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0)
 		printk(KERN_INFO "ipv6 esp close: can't remove xfrm type\n");
 }
 
diff -urN linux-2.5.65-bk4/net/ipv6/exthdrs.c linux-2.5.65-bk5/net/ipv6/exthdrs.c
--- linux-2.5.65-bk4/net/ipv6/exthdrs.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk5/net/ipv6/exthdrs.c	Mon Mar 31 12:44:34 2003
@@ -18,6 +18,9 @@
 /* Changes:
  *	yoshfuji		: ensure not to overrun while parsing 
  *				  tlv options.
+ *	Mitsuru KANDA @USAGI	: Remove ipv6_parse_exthdrs().
+ *				: Register inbound extention header
+ *				: handlers as inet6_protocol{}.
  */
 
 #include <linux/errno.h>
@@ -44,20 +47,6 @@
 #include <asm/uaccess.h>
 
 /*
- *	Parsing inbound headers.
- *
- *	Parsing function "func" returns offset wrt skb->nh of the place,
- *	where next nexthdr value is stored or NULL, if parsing
- *	failed. It should also update skb->h tp point at the next header.
- */
-
-struct hdrtype_proc
-{
-	int	type;
-	int	(*func) (struct sk_buff **, int offset);
-};
-
-/*
  *	Parsing tlv encoded headers.
  *
  *	Parsing function "func" returns 1, if parsing succeed
@@ -164,49 +153,77 @@
 	{-1,			NULL}
 };
 
-static int ipv6_dest_opt(struct sk_buff **skb_ptr, int nhoff)
+static int ipv6_destopt_rcv(struct sk_buff **skbp) 
 {
-	struct sk_buff *skb=*skb_ptr;
+	struct sk_buff *skb = *skbp;
 	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
+	u8 nexthdr = 0;
 
 	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
 	    !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
+	nexthdr = ((struct ipv6_destopt_hdr *)skb->h.raw)->nexthdr;
+	
 	opt->dst1 = skb->h.raw - skb->nh.raw;
 
 	if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
 		skb->h.raw += ((skb->h.raw[1]+1)<<3);
-		return opt->dst1;
+		return -nexthdr;
 	}
+						
+	return 0;
+}
 
-	return -1;
+static struct inet6_protocol destopt_protocol =
+{
+	.handler 	= 	ipv6_destopt_rcv,
+};
+
+void __init ipv6_destopt_init(void)
+{
+	if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0) 
+		printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
 }
 
 /********************************
   NONE header. No data in packet.
  ********************************/
 
-static int ipv6_nodata(struct sk_buff **skb_ptr, int nhoff)
+static int ipv6_nodata_rcv(struct sk_buff **skbp)
 {
-	kfree_skb(*skb_ptr);
-	return -1;
+	struct sk_buff *skb = *skbp;
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static struct inet6_protocol nodata_protocol =
+{
+	.handler	=	ipv6_nodata_rcv,
+};
+
+void __init ipv6_nodata_init(void)
+{
+	if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
+		printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
 }
 
 /********************************
   Routing header.
  ********************************/
 
-static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
+static int ipv6_rthdr_rcv(struct sk_buff **skbp)
 {
-	struct sk_buff *skb = *skb_ptr;
+	struct sk_buff *skb = *skbp;
 	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
 	struct in6_addr *addr;
 	struct in6_addr daddr;
 	int addr_type;
 	int n, i;
+	u8 nexthdr = 0;
 
 	struct ipv6_rt_hdr *hdr;
 	struct rt0_hdr *rthdr;
@@ -215,15 +232,16 @@
 	    !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
 		IP6_INC_STATS_BH(Ip6InHdrErrors);
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
 	hdr = (struct ipv6_rt_hdr *) skb->h.raw;
+	nexthdr = hdr->nexthdr;
 
 	if ((ipv6_addr_type(&skb->nh.ipv6h->daddr)&IPV6_ADDR_MULTICAST) ||
 	    skb->pkt_type != PACKET_HOST) {
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
 looped_back:
@@ -232,24 +250,24 @@
 		skb->h.raw += (hdr->hdrlen + 1) << 3;
 		opt->dst0 = opt->dst1;
 		opt->dst1 = 0;
-		return (&hdr->nexthdr) - skb->nh.raw;
+		return -nexthdr;
 	}
 
 	if (hdr->type != IPV6_SRCRT_TYPE_0 || (hdr->hdrlen & 0x01)) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, hdr->type != IPV6_SRCRT_TYPE_0 ? 2 : 1);
-		return -1;
+		return 0;
 	}
 
 	/*
 	 *	This is the routing header forwarding algorithm from
-	 *	RFC 1883, page 17.
+	 *	RFC 2460, page 16.
 	 */
 
 	n = hdr->hdrlen >> 1;
 
 	if (hdr->segments_left > n) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
-		return -1;
+		return 0;
 	}
 
 	/* We are about to mangle packet header. Be careful!
@@ -259,8 +277,8 @@
 		struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
 		kfree_skb(skb);
 		if (skb2 == NULL)
-			return -1;
-		*skb_ptr = skb = skb2;
+			return 0;
+		*skbp = skb = skb2;
 		opt = (struct inet6_skb_parm *)skb2->cb;
 		hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
 	}
@@ -278,7 +296,7 @@
 
 	if (addr_type&IPV6_ADDR_MULTICAST) {
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
 	ipv6_addr_copy(&daddr, addr);
@@ -289,23 +307,34 @@
 	ip6_route_input(skb);
 	if (skb->dst->error) {
 		dst_input(skb);
-		return -1;
+		return 0;
 	}
 	if (skb->dst->dev->flags&IFF_LOOPBACK) {
 		if (skb->nh.ipv6h->hop_limit <= 1) {
 			icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
 				    0, skb->dev);
 			kfree_skb(skb);
-			return -1;
+			return 0;
 		}
 		skb->nh.ipv6h->hop_limit--;
 		goto looped_back;
 	}
 
 	dst_input(skb);
-	return -1;
+	return 0;
 }
 
+static struct inet6_protocol rthdr_protocol =
+{
+	.handler	=	ipv6_rthdr_rcv,
+};
+
+void __init ipv6_rthdr_init(void)
+{
+	if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
+		printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
+};
+
 /*
    This function inverts received rthdr.
    NOTE: specs allow to make it automatically only if
@@ -371,97 +400,6 @@
 	return opt;
 }
 
-/********************************
-  AUTH header.
- ********************************/
-
-/*
-   rfc1826 said, that if a host does not implement AUTH header
-   it MAY ignore it. We use this hole 8)
-
-   Actually, now we can implement OSPFv6 without kernel IPsec.
-   Authentication for poors may be done in user space with the same success.
-
-   Yes, it means, that we allow application to send/receive
-   raw authentication header. Apparently, we suppose, that it knows
-   what it does and calculates authentication data correctly.
-   Certainly, it is possible only for udp and raw sockets, but not for tcp.
-
-   AUTH header has 4byte granular length, which kills all the idea
-   behind AUTOMATIC 64bit alignment of IPv6. Now we will lose
-   cpu ticks, checking that sender did not something stupid
-   and opt->hdrlen is even. Shit!		--ANK (980730)
- */
-
-static int ipv6_auth_hdr(struct sk_buff **skb_ptr, int nhoff)
-{
-	struct sk_buff *skb=*skb_ptr;
-	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-	int len;
-
-	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8))
-		goto fail;
-
-	/*
-	 * RFC2402 2.2 Payload Length
-	 * The 8-bit field specifies the length of AH in 32-bit words 
-	 * (4-byte units), minus "2".
-	 * -- Noriaki Takamiya @USAGI Project
-	 */
-	len = (skb->h.raw[1]+2)<<2;
-
-	if (len&7)
-		goto fail;
-
-	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+len))
-		goto fail;
-
-	opt->auth = skb->h.raw - skb->nh.raw;
-	skb->h.raw += len;
-	return opt->auth;
-
-fail:
-	kfree_skb(skb);
-	return -1;
-}
-
-/* This list MUST NOT contain entry for NEXTHDR_HOP.
-   It is parsed immediately after packet received
-   and if it occurs somewhere in another place we must
-   generate error.
- */
-
-static struct hdrtype_proc hdrproc_lst[] = {
-	{NEXTHDR_FRAGMENT,	ipv6_reassembly},
-	{NEXTHDR_ROUTING,	ipv6_routing_header},
-	{NEXTHDR_DEST,		ipv6_dest_opt},
-	{NEXTHDR_NONE,		ipv6_nodata},
-	{NEXTHDR_AUTH,		ipv6_auth_hdr},
-   /*
-	{NEXTHDR_ESP,		ipv6_esp_hdr},
-    */
-	{-1,			NULL}
-};
-
-int ipv6_parse_exthdrs(struct sk_buff **skb_in, int nhoff)
-{
-	struct hdrtype_proc *hdrt;
-	u8 nexthdr = (*skb_in)->nh.raw[nhoff];
-
-restart:
-	for (hdrt=hdrproc_lst; hdrt->type >= 0; hdrt++) {
-		if (hdrt->type == nexthdr) {
-			if ((nhoff = hdrt->func(skb_in, nhoff)) >= 0) {
-				nexthdr = (*skb_in)->nh.raw[nhoff];
-				goto restart;
-			}
-			return -1;
-		}
-	}
-	return nhoff;
-}
-
-
 /**********************************
   Hop-by-hop options.
  **********************************/
@@ -532,6 +470,34 @@
 	return -1;
 }
 
+/* This is fake. We have already parsed hopopts in ipv6_rcv(). -mk */
+static int ipv6_hopopts_rcv(struct sk_buff **skbp)
+{
+	struct sk_buff *skb = *skbp;
+	u8 nexthdr = 0;
+
+	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
+	    !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
+		kfree_skb(skb);
+		return 0;
+	}
+	nexthdr = ((struct ipv6_hopopt_hdr *)skb->h.raw)->nexthdr;
+	skb->h.raw += (skb->h.raw[1]+1)<<3;
+
+       return -nexthdr;
+}
+
+static struct inet6_protocol hopopts_protocol =
+{
+	.handler	=	ipv6_hopopts_rcv,
+};
+
+void __init ipv6_hopopts_init(void)
+{
+	if (inet6_add_protocol(&hopopts_protocol, IPPROTO_HOPOPTS) < 0)
+		printk(KERN_ERR "ipv6_hopopts_init: Could not register protocol\n");
+}
+
 /*
  *	Creating outbound headers.
  *
diff -urN linux-2.5.65-bk4/net/ipv6/icmp.c linux-2.5.65-bk5/net/ipv6/icmp.c
--- linux-2.5.65-bk4/net/ipv6/icmp.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/icmp.c	Mon Mar 31 12:44:34 2003
@@ -74,7 +74,7 @@
 static struct socket *__icmpv6_socket[NR_CPUS];
 #define icmpv6_socket	__icmpv6_socket[smp_processor_id()]
 
-static int icmpv6_rcv(struct sk_buff *skb);
+static int icmpv6_rcv(struct sk_buff **pskb);
 
 static struct inet6_protocol icmpv6_protocol = {
 	.handler	=	icmpv6_rcv,
@@ -459,8 +459,9 @@
  *	Handle icmp messages
  */
 
-static int icmpv6_rcv(struct sk_buff *skb)
+static int icmpv6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr, *daddr;
 	struct ipv6hdr *orig_hdr;
diff -urN linux-2.5.65-bk4/net/ipv6/ip6_input.c linux-2.5.65-bk5/net/ipv6/ip6_input.c
--- linux-2.5.65-bk4/net/ipv6/ip6_input.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk5/net/ipv6/ip6_input.c	Mon Mar 31 12:44:34 2003
@@ -15,6 +15,10 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+/* Changes
+ *
+ * 	Mitsuru KANDA @USAGI	: Remove ipv6_parse_exthdrs().
+ */
 
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -126,39 +130,11 @@
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
 	struct inet6_protocol *ipprot;
 	struct sock *raw_sk;
-	int nhoff;
-	int nexthdr;
+	int nexthdr = hdr->nexthdr;
 	u8 hash;
 
 	skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
 
-	/*
-	 *	Parse extension headers
-	 */
-
-	nexthdr = hdr->nexthdr;
-	nhoff = offsetof(struct ipv6hdr, nexthdr);
-
-	/* Skip  hop-by-hop options, they are already parsed. */
-	if (nexthdr == NEXTHDR_HOP) {
-		nhoff = sizeof(struct ipv6hdr);
-		nexthdr = skb->h.raw[0];
-		skb->h.raw += (skb->h.raw[1]+1)<<3;
-	}
-
-	/* This check is sort of optimization.
-	   It would be stupid to detect for optional headers,
-	   which are missing with probability of 200%
-	 */
-	if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP &&
-	    nexthdr != NEXTHDR_AUTH && nexthdr != NEXTHDR_ESP) {
-		nhoff = ipv6_parse_exthdrs(&skb, nhoff);
-		if (nhoff < 0)
-			return 0;
-		nexthdr = skb->nh.raw[nhoff];
-		hdr = skb->nh.ipv6h;
-	}
-
 	if (!pskb_pull(skb, skb->h.raw - skb->data))
 		goto discard;
 
@@ -173,7 +149,7 @@
 
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
 	if ((ipprot = inet6_protos[hash]) != NULL) {
-		int ret = ipprot->handler(skb);
+		int ret = ipprot->handler(&skb);
 		if (ret < 0) {
 			nexthdr = -ret;
 			goto resubmit;
@@ -182,7 +158,8 @@
 	} else {
 		if (!raw_sk) {
 			IP6_INC_STATS_BH(Ip6InUnknownProtos);
-			icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff);
+			icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR,
+					  offsetof(struct ipv6hdr, nexthdr));
 		} else {
 			IP6_INC_STATS_BH(Ip6InDelivers);
 			kfree_skb(skb);
diff -urN linux-2.5.65-bk4/net/ipv6/ip6_output.c linux-2.5.65-bk5/net/ipv6/ip6_output.c
--- linux-2.5.65-bk4/net/ipv6/ip6_output.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk5/net/ipv6/ip6_output.c	Mon Mar 31 12:44:34 2003
@@ -643,7 +643,8 @@
 		if (flags&MSG_PROBE)
 			goto out;
 		/* alloc skb with mtu as we do in the IPv4 stack for IPsec */
-		skb = sock_alloc_send_skb(sk, mtu, flags & MSG_DONTWAIT, &err);
+		skb = sock_alloc_send_skb(sk, mtu + LL_RESERVED_SPACE(dev),
+					  flags & MSG_DONTWAIT, &err);
 
 		if (skb == NULL) {
 			IP6_INC_STATS(Ip6OutDiscards);
diff -urN linux-2.5.65-bk4/net/ipv6/ipv6_sockglue.c linux-2.5.65-bk5/net/ipv6/ipv6_sockglue.c
--- linux-2.5.65-bk4/net/ipv6/ipv6_sockglue.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/ipv6/ipv6_sockglue.c	Mon Mar 31 12:44:34 2003
@@ -47,6 +47,7 @@
 #include <net/inet_common.h>
 #include <net/tcp.h>
 #include <net/udp.h>
+#include <net/xfrm.h>
 
 #include <asm/uaccess.h>
 
@@ -404,6 +405,10 @@
 	case IPV6_FLOWLABEL_MGR:
 		retv = ipv6_flowlabel_opt(sk, optval, optlen);
 		break;
+	case IPV6_IPSEC_POLICY:
+	case IPV6_XFRM_POLICY:
+		retv = xfrm_user_policy(sk, optname, optval, optlen);
+		break;
 
 #ifdef CONFIG_NETFILTER
 	default:
diff -urN linux-2.5.65-bk4/net/ipv6/ipv6_syms.c linux-2.5.65-bk5/net/ipv6/ipv6_syms.c
--- linux-2.5.65-bk4/net/ipv6/ipv6_syms.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk5/net/ipv6/ipv6_syms.c	Mon Mar 31 12:44:34 2003
@@ -5,6 +5,7 @@
 #include <net/ipv6.h>
 #include <net/addrconf.h>
 #include <net/ip6_route.h>
+#include <net/xfrm.h>
 
 EXPORT_SYMBOL(ipv6_addr_type);
 EXPORT_SYMBOL(icmpv6_send);
@@ -31,3 +32,5 @@
 EXPORT_SYMBOL(ipv6_chk_addr);
 EXPORT_SYMBOL(in6addr_any);
 EXPORT_SYMBOL(in6addr_loopback);
+EXPORT_SYMBOL(xfrm6_rcv);
+EXPORT_SYMBOL(xfrm6_clear_mutable_options);
diff -urN linux-2.5.65-bk4/net/ipv6/reassembly.c linux-2.5.65-bk5/net/ipv6/reassembly.c
--- linux-2.5.65-bk4/net/ipv6/reassembly.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk5/net/ipv6/reassembly.c	Mon Mar 31 12:44:34 2003
@@ -23,6 +23,7 @@
  *      Horst von Brand Add missing #include <linux/string.h>
  *	Alexey Kuznetsov	SMP races, threading, cleanup.
  *	Patrick McHardy		LRU queue of frag heads for evictor.
+ *	Mitsuru KANDA @USAGI	Register inet6_protocol{}.
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -525,6 +526,7 @@
 	int    remove_fraghdr = 0;
 	int    payload_len;
 	int    nhoff;
+	u8     nexthdr = 0;
 
 	fq_kill(fq);
 
@@ -535,6 +537,8 @@
 	payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len;
 	nhoff = head->h.raw - head->nh.raw;
 
+	nexthdr = ((struct frag_hdr*)head->h.raw)->nexthdr;
+
 	if (payload_len > 65535) {
 		payload_len -= 8;
 		if (payload_len > 65535)
@@ -609,9 +613,12 @@
 	if (head->ip_summed == CHECKSUM_HW)
 		head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
 
+	if (!pskb_pull(head, head->h.raw - head->data))
+		goto out_fail;
+
 	IP6_INC_STATS_BH(Ip6ReasmOKs);
 	fq->fragments = NULL;
-	return nhoff;
+	return nexthdr;
 
 out_oversize:
 	if (net_ratelimit())
@@ -622,16 +629,18 @@
 		printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
 out_fail:
 	IP6_INC_STATS_BH(Ip6ReasmFails);
-	return -1;
+	return 0;
 }
 
-int ipv6_reassembly(struct sk_buff **skbp, int nhoff)
+static int ipv6_frag_rcv(struct sk_buff **skbp)
 {
 	struct sk_buff *skb = *skbp; 
 	struct net_device *dev = skb->dev;
 	struct frag_hdr *fhdr;
 	struct frag_queue *fq;
 	struct ipv6hdr *hdr;
+	int nhoff = skb->h.raw - skb->nh.raw;
+	u8 nexthdr = 0;
 
 	hdr = skb->nh.ipv6h;
 
@@ -640,15 +649,16 @@
 	/* Jumbo payload inhibits frag. header */
 	if (hdr->payload_len==0) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
-		return -1;
+		goto discard;
 	}
 	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
-		return -1;
+		goto discard;
 	}
 
 	hdr = skb->nh.ipv6h;
 	fhdr = (struct frag_hdr *)skb->h.raw;
+	nexthdr = fhdr->nexthdr;
 
 	if (!(fhdr->frag_off & htons(0xFFF9))) {
 		/* It is not a fragmented frame */
@@ -674,10 +684,22 @@
 
 		spin_unlock(&fq->lock);
 		fq_put(fq);
-		return ret;
+		return -ret;
 	}
 
+discard:
 	IP6_INC_STATS_BH(Ip6ReasmFails);
 	kfree_skb(skb);
-	return -1;
+	return 0;
+}
+
+static struct inet6_protocol frag_protocol =
+{
+	.handler	=	ipv6_frag_rcv,
+};
+
+void __init ipv6_frag_init(void)
+{
+	if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0)
+		printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n");
 }
diff -urN linux-2.5.65-bk4/net/ipv6/route.c linux-2.5.65-bk5/net/ipv6/route.c
--- linux-2.5.65-bk4/net/ipv6/route.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk5/net/ipv6/route.c	Mon Mar 31 12:44:34 2003
@@ -1867,15 +1867,6 @@
 
 #endif
 
-int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
-{
-	int err = 0;
-	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
-	if (!*dst)
-		err = -ENETUNREACH;
-	return err;
-}
-
 void __init ip6_route_init(void)
 {
 	ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",
@@ -1883,11 +1874,11 @@
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
 	fib6_init();
-	xfrm_dst_lookup_register(xfrm6_dst_lookup, AF_INET6);
 #ifdef 	CONFIG_PROC_FS
 	proc_net_create("ipv6_route", 0, rt6_proc_info);
 	proc_net_create("rt6_stats", 0, rt6_proc_stats);
 #endif
+	xfrm6_init();
 }
 
 #ifdef MODULE
@@ -1897,7 +1888,7 @@
 	proc_net_remove("ipv6_route");
 	proc_net_remove("rt6_stats");
 #endif
-	xfrm_dst_lookup_unregister(AF_INET6);
+	xfrm6_fini();
 	rt6_ifdown(NULL);
 	fib6_gc_cleanup();
 }
diff -urN linux-2.5.65-bk4/net/ipv6/tcp_ipv6.c linux-2.5.65-bk5/net/ipv6/tcp_ipv6.c
--- linux-2.5.65-bk4/net/ipv6/tcp_ipv6.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk5/net/ipv6/tcp_ipv6.c	Mon Mar 31 12:44:34 2003
@@ -967,7 +967,7 @@
 	struct ipv6_pinfo *np = inet6_sk(sk);
 
 	if (skb->ip_summed == CHECKSUM_HW) {
-		th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,  0);
+		th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,  0);
 		skb->csum = offsetof(struct tcphdr, check);
 	} else {
 		th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 
@@ -1591,8 +1591,9 @@
 	return 0;
 }
 
-static int tcp_v6_rcv(struct sk_buff *skb)
+static int tcp_v6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	struct tcphdr *th;	
 	struct sock *sk;
 	int ret;
@@ -1642,7 +1643,7 @@
 		goto discard_and_relse;
 
 	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
-		goto discard_it;
+		goto discard_and_relse;
 
 	skb->dev = NULL;
 
diff -urN linux-2.5.65-bk4/net/ipv6/udp.c linux-2.5.65-bk5/net/ipv6/udp.c
--- linux-2.5.65-bk4/net/ipv6/udp.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk5/net/ipv6/udp.c	Mon Mar 31 12:44:34 2003
@@ -641,8 +641,9 @@
 	read_unlock(&udp_hash_lock);
 }
 
-static int udpv6_rcv(struct sk_buff *skb)
+static int udpv6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	struct sock *sk;
   	struct udphdr *uh;
 	struct net_device *dev = skb->dev;
diff -urN linux-2.5.65-bk4/net/ipv6/xfrm6_input.c linux-2.5.65-bk5/net/ipv6/xfrm6_input.c
--- linux-2.5.65-bk4/net/ipv6/xfrm6_input.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/net/ipv6/xfrm6_input.c	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,262 @@
+/*
+ * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
+ *
+ * Authors:
+ *	Mitsuru KANDA @USAGI
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	Kunihiro Ishiguro
+ *	YOSHIFUJI Hideaki @USAGI
+ *		IPv6 support
+ */
+
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+static kmem_cache_t *secpath_cachep;
+
+static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
+{
+	u8 *opt = (u8 *)opthdr;
+	int len = ipv6_optlen(opthdr);
+	int off = 0;
+	int optlen = 0;
+
+	off += 2;
+	len -= 2;
+
+	while (len > 0) {
+
+		switch (opt[off]) {
+
+		case IPV6_TLV_PAD0:
+			optlen = 1;
+			break;
+		default:
+			if (len < 2) 
+				goto bad;
+			optlen = opt[off+1]+2;
+			if (len < optlen)
+				goto bad;
+			if (opt[off] & 0x20)
+				memset(&opt[off+2], 0, opt[off+1]);
+			break;
+		}
+
+		off += optlen;
+		len -= optlen;
+	}
+	if (len == 0)
+		return 1;
+
+bad:
+	return 0;
+}
+
+int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+	unsigned int packet_len = skb->tail - skb->nh.raw;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+	u8 nextnexthdr = 0;
+
+	*nh_offset = ((unsigned char *)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+
+	while (offset + 1 <= packet_len) {
+
+		switch (nexthdr) {
+
+		case NEXTHDR_HOP:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			if (!zero_out_mutable_opts(exthdr)) {
+				if (net_ratelimit())
+					printk(KERN_WARNING "overrun hopopts\n"); 
+				return 0;
+			}
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_ROUTING:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			((struct ipv6_rt_hdr*)exthdr)->segments_left = 0; 
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_DEST:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			if (!zero_out_mutable_opts(exthdr))  {
+				if (net_ratelimit())
+					printk(KERN_WARNING "overrun destopt\n"); 
+				return 0;
+			}
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_AUTH:
+			if (dir == XFRM_POLICY_OUT) {
+				memset(((struct ipv6_auth_hdr*)exthdr)->auth_data, 0, 
+				       (((struct ipv6_auth_hdr*)exthdr)->hdrlen - 1) << 2);
+			}
+			if (exthdr->nexthdr == NEXTHDR_DEST) {
+				offset += (((struct ipv6_auth_hdr*)exthdr)->hdrlen + 2) << 2;
+				exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+				nextnexthdr = exthdr->nexthdr;
+				if (!zero_out_mutable_opts(exthdr)) {
+					if (net_ratelimit())
+						printk(KERN_WARNING "overrun destopt\n");
+					return 0;
+				}
+			}
+			return nexthdr;
+		default :
+			return nexthdr;
+		}
+	}
+
+	return nexthdr;
+}
+
+int xfrm6_rcv(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	int err;
+	u32 spi, seq;
+	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
+	struct xfrm_state *x;
+	int xfrm_nr = 0;
+	int decaps = 0;
+	struct ipv6hdr *hdr = skb->nh.ipv6h;
+	unsigned char *tmp_hdr = NULL;
+	int hdr_len = 0;
+	u16 nh_offset = 0;
+	u8 nexthdr = 0;
+
+	nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+	hdr_len = sizeof(struct ipv6hdr);
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto drop;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+
+	nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN);
+	hdr->priority    = 0;
+	hdr->flow_lbl[0] = 0;
+	hdr->flow_lbl[1] = 0;
+	hdr->flow_lbl[2] = 0;
+	hdr->hop_limit   = 0;
+
+	if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+		goto drop;
+	
+	do {
+		struct ipv6hdr *iph = skb->nh.ipv6h;
+
+		if (xfrm_nr == XFRM_MAX_DEPTH)
+			goto drop;
+
+		x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, nexthdr, AF_INET6);
+		if (x == NULL)
+			goto drop;
+		spin_lock(&x->lock);
+		if (unlikely(x->km.state != XFRM_STATE_VALID))
+			goto drop_unlock;
+
+		if (x->props.replay_window && xfrm_replay_check(x, seq))
+			goto drop_unlock;
+
+		nexthdr = x->type->input(x, skb);
+		if (nexthdr <= 0)
+			goto drop_unlock;
+
+		if (x->props.replay_window)
+			xfrm_replay_advance(x, seq);
+
+		x->curlft.bytes += skb->len;
+		x->curlft.packets++;
+
+		spin_unlock(&x->lock);
+
+		xfrm_vec[xfrm_nr++] = x;
+
+		if (x->props.mode) { /* XXX */
+			if (iph->nexthdr != IPPROTO_IPV6)
+				goto drop;
+			skb->nh.raw = skb->data;
+			iph = skb->nh.ipv6h;
+			decaps = 1;
+			break;
+		}
+
+		if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
+			goto drop;
+	} while (!err);
+
+	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	skb->nh.raw[nh_offset] = nexthdr;
+	skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
+
+	/* Allocate new secpath or COW existing one. */
+	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+		kmem_cache_t *pool = skb->sp ? skb->sp->pool : secpath_cachep;
+		struct sec_path *sp;
+		sp = kmem_cache_alloc(pool, SLAB_ATOMIC);
+		if (!sp)
+			goto drop;
+		if (skb->sp) {
+			memcpy(sp, skb->sp, sizeof(struct sec_path));
+			secpath_put(skb->sp);
+		} else {
+			sp->pool = pool;
+			sp->len = 0;
+		}
+		atomic_set(&sp->refcnt, 1);
+		skb->sp = sp;
+	}
+
+	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
+		goto drop;
+
+	memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*));
+	skb->sp->len += xfrm_nr;
+
+	if (decaps) {
+		if (!(skb->dev->flags&IFF_LOOPBACK)) {
+			dst_release(skb->dst);
+			skb->dst = NULL;
+		}
+		netif_rx(skb);
+		return 0;
+	} else {
+		return -nexthdr;
+	}
+
+drop_unlock:
+	spin_unlock(&x->lock);
+	xfrm_state_put(x);
+drop:
+	if (tmp_hdr) kfree(tmp_hdr);
+	while (--xfrm_nr >= 0)
+		xfrm_state_put(xfrm_vec[xfrm_nr]);
+	kfree_skb(skb);
+	return 0;
+}
+
+void __init xfrm6_input_init(void)
+{
+	secpath_cachep = kmem_cache_create("secpath6_cache",
+					   sizeof(struct sec_path),
+					   0, SLAB_HWCACHE_ALIGN,
+					   NULL, NULL);
+
+	if (!secpath_cachep)
+		panic("IPv6: failed to allocate secpath6_cache\n");
+}
+
diff -urN linux-2.5.65-bk4/net/ipv6/xfrm6_policy.c linux-2.5.65-bk5/net/ipv6/xfrm6_policy.c
--- linux-2.5.65-bk4/net/ipv6/xfrm6_policy.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/net/ipv6/xfrm6_policy.c	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,273 @@
+/*
+ * xfrm6_policy.c: based on xfrm4_policy.c
+ *
+ * Authors:
+ *	Mitsuru KANDA @USAGI
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	Kunihiro Ishiguro
+ * 		IPv6 support
+ * 	YOSHIFUJI Hideaki
+ * 		Split up af-specific portion
+ * 
+ */
+
+#include <linux/config.h>
+#include <net/xfrm.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+
+extern struct dst_ops xfrm6_dst_ops;
+extern struct xfrm_policy_afinfo xfrm6_policy_afinfo;
+
+static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED };
+
+int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+	int err = 0;
+	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
+	if (!*dst)
+		err = -ENETUNREACH;
+	return err;
+}
+
+/* Check that the bundle accepts the flow and its components are
+ * still valid.
+ */
+
+static int __xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
+{
+	do {
+		if (xdst->u.dst.ops != &xfrm6_dst_ops)
+			return 1;
+
+		if (!xfrm_selector_match(&xdst->u.dst.xfrm->sel, fl, AF_INET6))
+			return 0;
+		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
+		    xdst->u.dst.path->obsolete > 0)
+			return 0;
+		xdst = (struct xfrm_dst*)xdst->u.dst.child;
+	} while (xdst);
+	return 0;
+}
+
+static struct dst_entry *
+__xfrm6_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy)
+{
+	struct dst_entry *dst;
+
+	/* Still not clear if we should set fl->fl6_{src,dst}... */
+	read_lock_bh(&policy->lock);
+	for (dst = policy->bundles; dst; dst = dst->next) {
+		struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+		if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, fl->fl6_dst) &&
+		    !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, fl->fl6_src) &&
+		    __xfrm6_bundle_ok(xdst, fl)) {
+			dst_clone(dst);
+			break;
+		}
+	}
+	read_unlock_bh(&policy->lock);
+	return dst;
+}
+
+/* Allocate chain of dst_entry's, attach known xfrm's, calculate
+ * all the metrics... Shortly, bundle a bundle.
+ */
+
+static int
+__xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
+		      struct flowi *fl, struct dst_entry **dst_p)
+{
+	struct dst_entry *dst, *dst_prev;
+	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+	struct rt6_info *rt  = rt0;
+	struct in6_addr *remote = fl->fl6_dst;
+	struct in6_addr *local  = fl->fl6_src;
+	int i;
+	int err = 0;
+	int header_len = 0;
+	int trailer_len = 0;
+
+	dst = dst_prev = NULL;
+
+	for (i = 0; i < nx; i++) {
+		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+
+		if (unlikely(dst1 == NULL)) {
+			err = -ENOBUFS;
+			goto error;
+		}
+
+		dst1->xfrm = xfrm[i];
+		if (!dst)
+			dst = dst1;
+		else {
+			dst_prev->child = dst1;
+			dst1->flags |= DST_NOHASH;
+			dst_clone(dst1);
+		}
+		dst_prev = dst1;
+		if (xfrm[i]->props.mode) {
+			remote = (struct in6_addr*)&xfrm[i]->id.daddr;
+			local  = (struct in6_addr*)&xfrm[i]->props.saddr;
+		}
+		header_len += xfrm[i]->props.header_len;
+		trailer_len += xfrm[i]->props.trailer_len;
+	}
+
+	if (ipv6_addr_cmp(remote, fl->fl6_dst)) {
+		struct flowi fl_tunnel = { .nl_u = { .ip6_u =
+						     { .daddr = remote,
+						       .saddr = local }
+					           }
+				         };
+		err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET6);
+		if (err)
+			goto error;
+	} else {
+		dst_hold(&rt->u.dst);
+	}
+	dst_prev->child = &rt->u.dst;
+	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		x->u.rt.fl = *fl;
+
+		dst_prev->dev = rt->u.dst.dev;
+		if (rt->u.dst.dev)
+			dev_hold(rt->u.dst.dev);
+		dst_prev->obsolete	= -1;
+		dst_prev->flags	       |= DST_HOST;
+		dst_prev->lastuse	= jiffies;
+		dst_prev->header_len	= header_len;
+		dst_prev->trailer_len	= trailer_len;
+		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
+		dst_prev->path		= &rt->u.dst;
+
+		/* Copy neighbout for reachability confirmation */
+		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
+		dst_prev->input		= rt->u.dst.input;
+		dst_prev->output	= dst_prev->xfrm->type->output;
+		/* Sheit... I remember I did this right. Apparently,
+		 * it was magically lost, so this code needs audit */
+		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
+		x->u.rt6.rt6i_metric   = rt0->rt6i_metric;
+		x->u.rt6.rt6i_node     = rt0->rt6i_node;
+		x->u.rt6.rt6i_hoplimit = rt0->rt6i_hoplimit;
+		x->u.rt6.rt6i_gateway  = rt0->rt6i_gateway;
+		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 
+		header_len -= x->u.dst.xfrm->props.header_len;
+		trailer_len -= x->u.dst.xfrm->props.trailer_len;
+	}
+	*dst_p = dst;
+	return 0;
+
+error:
+	if (dst)
+		dst_free(dst);
+	return err;
+}
+
+static inline void
+_decode_session6(struct sk_buff *skb, struct flowi *fl)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6hdr *hdr = skb->nh.ipv6h;
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+
+	fl->fl6_dst = &hdr->daddr;
+	fl->fl6_src = &hdr->saddr;
+
+	while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+		switch (nexthdr) {
+		case NEXTHDR_ROUTING:
+		case NEXTHDR_HOP:
+		case NEXTHDR_DEST:
+			offset += ipv6_optlen(exthdr);
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case IPPROTO_UDP:
+		case IPPROTO_TCP:
+		case IPPROTO_SCTP:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) {
+				u16 *ports = (u16 *)exthdr;
+
+				fl->uli_u.ports.sport = ports[0];
+				fl->uli_u.ports.dport = ports[1];
+			}
+			return;
+
+		/* XXX Why are there these headers? */
+		case IPPROTO_AH:
+		case IPPROTO_ESP:
+		default:
+			fl->uli_u.spi = 0;
+			return;
+		};
+	}
+}
+
+static inline int xfrm6_garbage_collect(void)
+{
+	read_lock(&xfrm6_policy_afinfo.lock);
+	xfrm6_policy_afinfo.garbage_collect();
+	read_unlock(&xfrm6_policy_afinfo.lock);
+	return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
+}
+
+static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+	struct dst_entry *path = dst->path;
+
+	if (mtu >= 1280 && mtu < dst_pmtu(dst))
+		return;
+
+	path->ops->update_pmtu(path, mtu);
+}
+
+struct dst_ops xfrm6_dst_ops = {
+	.family =		AF_INET6,
+	.protocol =		__constant_htons(ETH_P_IPV6),
+	.gc =			xfrm6_garbage_collect,
+	.update_pmtu =		xfrm6_update_pmtu,
+	.gc_thresh =		1024,
+	.entry_size =		sizeof(struct xfrm_dst),
+};
+
+struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
+	.family =		AF_INET6,
+	.lock = 		RW_LOCK_UNLOCKED,
+	.type_map = 		&xfrm6_type_map,
+	.dst_ops =		&xfrm6_dst_ops,
+	.dst_lookup =		xfrm6_dst_lookup,
+	.find_bundle =		__xfrm6_find_bundle,
+	.bundle_create =	__xfrm6_bundle_create,
+	.decode_session =	_decode_session6,
+};
+
+void __init xfrm6_policy_init(void)
+{
+	xfrm_policy_register_afinfo(&xfrm6_policy_afinfo);
+}
+
+void __exit xfrm6_policy_fini(void)
+{
+	xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
+}
+
+void __init xfrm6_init(void)
+{
+	xfrm6_policy_init();
+	xfrm6_state_init();
+	xfrm6_input_init();
+}
+
+void __exit xfrm6_fini(void)
+{
+	//xfrm6_input_fini();
+	xfrm6_policy_fini();
+	xfrm6_state_fini();
+}
diff -urN linux-2.5.65-bk4/net/ipv6/xfrm6_state.c linux-2.5.65-bk5/net/ipv6/xfrm6_state.c
--- linux-2.5.65-bk4/net/ipv6/xfrm6_state.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk5/net/ipv6/xfrm6_state.c	Mon Mar 31 12:44:34 2003
@@ -0,0 +1,134 @@
+/*
+ * xfrm6_state.c: based on xfrm4_state.c
+ *
+ * Authors:
+ *	Mitsuru KANDA @USAGI
+ * 	Kazunori MIYAZAWA @USAGI
+ * 	Kunihiro Ishiguro
+ * 		IPv6 support
+ * 	YOSHIFUJI Hideaki @USAGI
+ * 		Split up af-specific portion
+ * 	
+ */
+
+#include <net/xfrm.h>
+#include <linux/pfkeyv2.h>
+#include <linux/ipsec.h>
+#include <net/ipv6.h>
+
+extern struct xfrm_state_afinfo xfrm6_state_afinfo;
+
+static void
+__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
+		     struct xfrm_tmpl *tmpl,
+		     xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
+	/* Initialize temporary selector matching only
+	 * to current session. */
+	memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr));
+	memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr));
+	x->sel.dport = fl->uli_u.ports.dport;
+	x->sel.dport_mask = ~0;
+	x->sel.sport = fl->uli_u.ports.sport;
+	x->sel.sport_mask = ~0;
+	x->sel.prefixlen_d = 128;
+	x->sel.prefixlen_s = 128;
+	x->sel.proto = fl->proto;
+	x->sel.ifindex = fl->oif;
+	x->id = tmpl->id;
+	if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
+		memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
+	memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
+	if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
+		memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
+	x->props.mode = tmpl->mode;
+	x->props.reqid = tmpl->reqid;
+	x->props.family = AF_INET6;
+}
+
+static struct xfrm_state *
+__xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
+{
+	unsigned h = __xfrm6_spi_hash(daddr, spi, proto);
+	struct xfrm_state *x;
+
+	list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) {
+		if (x->props.family == AF_INET6 &&
+		    spi == x->id.spi &&
+		    !ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
+		    proto == x->id.proto) {
+			atomic_inc(&x->refcnt);
+			return x;
+		}
+	}
+	return NULL;
+}
+
+static struct xfrm_state *
+__xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, 
+		 xfrm_address_t *daddr, xfrm_address_t *saddr, 
+		 int create)
+{
+	struct xfrm_state *x, *x0;
+	unsigned h = __xfrm6_dst_hash(daddr);
+
+	x0 = NULL;
+
+	list_for_each_entry(x, xfrm6_state_afinfo.state_bydst+h, bydst) {
+		if (x->props.family == AF_INET6 &&
+		    !ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
+		    mode == x->props.mode &&
+		    proto == x->id.proto &&
+		    !ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) &&
+		    reqid == x->props.reqid &&
+		    x->km.state == XFRM_STATE_ACQ) {
+			    if (!x0)
+				    x0 = x;
+			    if (x->id.spi)
+				    continue;
+			    x0 = x;
+			    break;
+		    }
+	}
+	if (x0) {
+		atomic_inc(&x0->refcnt);
+	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
+		memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
+		memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
+		x0->sel.prefixlen_d = 128;
+		x0->sel.prefixlen_s = 128;
+		memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
+		x0->km.state = XFRM_STATE_ACQ;
+		memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
+		x0->id.proto = proto;
+		x0->props.family = AF_INET6;
+		x0->props.mode = mode;
+		x0->props.reqid = reqid;
+		x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
+		atomic_inc(&x0->refcnt);
+		mod_timer(&x0->timer, jiffies + XFRM_ACQ_EXPIRES*HZ);
+		atomic_inc(&x0->refcnt);
+		list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h);
+		wake_up(&km_waitq);
+	}
+	return x0;
+}
+
+static struct xfrm_state_afinfo xfrm6_state_afinfo = {
+	.family			= AF_INET6,
+	.lock			= RW_LOCK_UNLOCKED,
+	.init_tempsel		= __xfrm6_init_tempsel,
+	.state_lookup		= __xfrm6_state_lookup,
+	.find_acq		= __xfrm6_find_acq,
+};
+
+void __init xfrm6_state_init(void)
+{
+	xfrm_state_register_afinfo(&xfrm6_state_afinfo);
+}
+
+void __exit xfrm6_state_fini(void)
+{
+	xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
+}
+
diff -urN linux-2.5.65-bk4/net/key/af_key.c linux-2.5.65-bk5/net/key/af_key.c
--- linux-2.5.65-bk4/net/key/af_key.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/key/af_key.c	Mon Mar 31 12:44:34 2003
@@ -510,10 +510,8 @@
 {
 	switch (((struct sockaddr*)(addr + 1))->sa_family) {
 	case AF_INET:
-		xaddr->xfrm4_addr = 
+		xaddr->a4 = 
 			((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr;
-		if (addr->sadb_address_prefixlen)
-			xaddr->xfrm4_mask = htonl(~0 << (32 - addr->sadb_address_prefixlen));
 		return AF_INET;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -530,10 +528,11 @@
 
 static struct  xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs)
 {
-	struct xfrm_state *x;
 	struct sadb_sa *sa;
 	struct sadb_address *addr;
 	uint16_t proto;
+	unsigned short family;
+	xfrm_address_t *xaddr;
 
 	sa = (struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
 	if (sa == NULL)
@@ -548,23 +547,24 @@
 	if (addr == NULL)
 		return NULL;
 
-	switch (((struct sockaddr *)(addr + 1))->sa_family) {
+	family = ((struct sockaddr *)(addr + 1))->sa_family;
+	switch (family) {
 	case AF_INET:
-		x = xfrm4_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr,
-				       sa->sadb_sa_spi, proto);
+		xaddr = (xfrm_address_t *)&((struct sockaddr_in *)(addr + 1))->sin_addr;
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
-		x = xfrm6_state_lookup(&((struct sockaddr_in6 *)(addr + 1))->sin6_addr,
-				       sa->sadb_sa_spi, proto);
+		xaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(addr + 1))->sin6_addr;
 		break;
 #endif
 	default:
-		x = NULL;
-		break;
+		xaddr = NULL;
 	}
 
-	return x;
+	if (!xaddr)
+		return NULL;
+
+	return xfrm_state_lookup(xaddr, sa->sadb_sa_spi, proto, family);
 }
 
 #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
@@ -619,7 +619,7 @@
 	/* identity & sensitivity */
 
 	if ((x->props.family == AF_INET &&
-	     x->sel.saddr.xfrm4_addr != x->props.saddr.xfrm4_addr)
+	     x->sel.saddr.a4 != x->props.saddr.a4)
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	    || (x->props.family == AF_INET6 &&
 		memcmp (x->sel.saddr.a6, x->props.saddr.a6, sizeof (struct in6_addr)))
@@ -667,10 +667,17 @@
 		sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0;
 	}
 	sa->sadb_sa_encrypt = 0;
+	BUG_ON(x->ealg && x->calg);
 	if (x->ealg) {
 		struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name);
 		sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0;
 	}
+	/* KAME compatible: sadb_sa_encrypt is overloaded with calg id */
+	if (x->calg) {
+		struct xfrm_algo_desc *a = xfrm_calg_get_byname(x->calg->alg_name);
+		sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0;
+	}
+
 	sa->sadb_sa_flags = 0;
 
 	/* hard time */
@@ -724,7 +731,7 @@
 
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
-		sin->sin_addr.s_addr = x->props.saddr.xfrm4_addr;
+		sin->sin_addr.s_addr = x->props.saddr.a4;
 		sin->sin_port = 0;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 	}
@@ -757,11 +764,11 @@
 	if (x->props.family == AF_INET) {
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
-		sin->sin_addr.s_addr = x->id.daddr.xfrm4_addr;
+		sin->sin_addr.s_addr = x->id.daddr.a4;
 		sin->sin_port = 0;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 
-		if (x->sel.saddr.xfrm4_addr != x->props.saddr.xfrm4_addr) {
+		if (x->sel.saddr.a4 != x->props.saddr.a4) {
 			addr = (struct sadb_address*) skb_put(skb, 
 				sizeof(struct sadb_address)+sockaddr_size);
 			addr->sadb_address_len = 
@@ -775,7 +782,7 @@
 
 			sin = (struct sockaddr_in *) (addr + 1);
 			sin->sin_family = AF_INET;
-			sin->sin_addr.s_addr = x->sel.saddr.xfrm4_addr;
+			sin->sin_addr.s_addr = x->sel.saddr.a4;
 			sin->sin_port = x->sel.sport;
 			memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 		}
@@ -896,6 +903,8 @@
 	   Hence, we have to _ignore_ sadb_sa_state, which is also reasonable.
 	 */
 	if (sa->sadb_sa_auth > SADB_AALG_MAX ||
+	    (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP &&
+	     sa->sadb_sa_encrypt > SADB_X_CALG_MAX) ||
 	    sa->sadb_sa_encrypt > SADB_EALG_MAX)
 		return ERR_PTR(-EINVAL);
 	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
@@ -953,24 +962,35 @@
 		x->props.aalgo = sa->sadb_sa_auth;
 		/* x->algo.flags = sa->sadb_sa_flags; */
 	}
-	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
 	if (sa->sadb_sa_encrypt) {
-		int keysize = 0;
-		struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);
-		if (!a)
-			goto out;
-		if (key)
-			keysize = (key->sadb_key_bits + 7) / 8;
-		x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
-		if (!x->ealg)
-			goto out;
-		strcpy(x->ealg->alg_name, a->name);
-		x->ealg->alg_key_len = 0;
-		if (key) {
-			x->ealg->alg_key_len = key->sadb_key_bits;
-			memcpy(x->ealg->alg_key, key+1, keysize);
+		if (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
+			struct xfrm_algo_desc *a = xfrm_calg_get_byid(sa->sadb_sa_encrypt);
+			if (!a)
+				goto out;
+			x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
+			if (!x->calg)
+				goto out;
+			strcpy(x->calg->alg_name, a->name);
+			x->props.calgo = sa->sadb_sa_encrypt;
+		} else {
+			int keysize = 0;
+			struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);
+			if (!a)
+				goto out;
+			key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
+			if (key)
+				keysize = (key->sadb_key_bits + 7) / 8;
+			x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
+			if (!x->ealg)
+				goto out;
+			strcpy(x->ealg->alg_name, a->name);
+			x->ealg->alg_key_len = 0;
+			if (key) {
+				x->ealg->alg_key_len = key->sadb_key_bits;
+				memcpy(x->ealg->alg_key, key+1, keysize);
+			}
+			x->props.ealgo = sa->sadb_sa_encrypt;
 		}
-		x->props.ealgo = sa->sadb_sa_encrypt;
 	}
 	/* x->algo.flags = sa->sadb_sa_flags; */
 
@@ -997,20 +1017,7 @@
 		x->sel.prefixlen_s = addr->sadb_address_prefixlen;
 	}
 
-	switch (x->props.family) {
-	case AF_INET:
-		x->type = xfrm_get_type(proto);
-		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-		x->type = xfrm6_get_type(proto);
-		break;
-#endif
-	default:
-		x->type = NULL;
-		break;
-	}
-
+	x->type = xfrm_get_type(proto, x->props.family);
 	if (x->type == NULL)
 		goto out;
 	if (x->type->init_state(x, NULL))
@@ -1024,6 +1031,8 @@
 		kfree(x->aalg);
 	if (x->ealg)
 		kfree(x->ealg);
+	if (x->calg)
+		kfree(x->calg);
 	kfree(x);
 	return ERR_PTR(-ENOBUFS);
 }
@@ -1039,10 +1048,12 @@
 	struct sadb_x_sa2 *sa2;
 	struct sadb_address *saddr, *daddr;
 	struct sadb_msg *out_hdr;
-	struct xfrm_state *x;
+	struct xfrm_state *x = NULL;
 	u8 mode;
 	u16 reqid;
 	u8 proto;
+	unsigned short family;
+	xfrm_address_t *xsaddr = NULL, *xdaddr = NULL;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
@@ -1063,23 +1074,21 @@
 	saddr = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
 	daddr = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
 
-	switch (((struct sockaddr *)(saddr + 1))->sa_family) {
+	family = ((struct sockaddr *)(saddr + 1))->sa_family;
+	switch (family) {
 	case AF_INET:
-		x = xfrm_find_acq(mode, reqid, proto,
-				  ((struct sockaddr_in *)(daddr + 1))->sin_addr.s_addr,
-				  ((struct sockaddr_in *)(saddr + 1))->sin_addr.s_addr, 1);
+		xdaddr = (xfrm_address_t *)&((struct sockaddr_in *)(daddr + 1))->sin_addr.s_addr;
+		xsaddr = (xfrm_address_t *)&((struct sockaddr_in *)(saddr + 1))->sin_addr.s_addr;
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
-		x = xfrm6_find_acq(mode, reqid, proto,
-				   &((struct sockaddr_in6 *)(daddr + 1))->sin6_addr,
-				   &((struct sockaddr_in6 *)(saddr + 1))->sin6_addr, 1);
+		xdaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(daddr + 1))->sin6_addr;
+		xsaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(saddr + 1))->sin6_addr;
 		break;
 #endif
-	default:
-		x = NULL;
-		break;
 	}
+	if (xdaddr)
+		x = xfrm_find_acq(mode, reqid, proto, xdaddr, xsaddr, 1, family);
 
 	if (x == NULL)
 		return -ENOENT;
@@ -1166,23 +1175,9 @@
 	/* XXX there is race condition */
 	x1 = pfkey_xfrm_state_lookup(hdr, ext_hdrs);
 	if (!x1) {
-		switch (x->props.family) {
-		case AF_INET:
-			x1 = xfrm_find_acq(x->props.mode, x->props.reqid, x->id.proto,
-					   x->id.daddr.xfrm4_addr,
-					   x->props.saddr.xfrm4_addr, 0);
-			break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			x1 = xfrm6_find_acq(x->props.mode, x->props.reqid, x->id.proto,
-					    (struct in6_addr*)x->id.daddr.a6,
-					    (struct in6_addr*)x->props.saddr.a6, 0);
-			break;
-#endif
-		default:
-			x1 = NULL;
-			break;
-		}
+		x1 = xfrm_find_acq(x->props.mode, x->props.reqid, x->id.proto,
+				   &x->id.daddr,
+				   &x->props.saddr, 0, x->props.family);
 		if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
 			xfrm_state_put(x1);
 			x1 = NULL;
@@ -1521,11 +1516,11 @@
 			sin = (void*)(rq+1);
 			if (sin->sin_family != AF_INET)
 				return -EINVAL;
-			t->saddr.xfrm4_addr = sin->sin_addr.s_addr;
+			t->saddr.a4 = sin->sin_addr.s_addr;
 			sin++;
 			if (sin->sin_family != AF_INET)
 				return -EINVAL;
-			t->id.daddr.xfrm4_addr = sin->sin_addr.s_addr;
+			t->id.daddr.a4 = sin->sin_addr.s_addr;
 			break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		case AF_INET6:
@@ -1632,7 +1627,7 @@
 	if (xp->family == AF_INET) {
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
-		sin->sin_addr.s_addr = xp->selector.saddr.xfrm4_addr;
+		sin->sin_addr.s_addr = xp->selector.saddr.a4;
 		sin->sin_port = xp->selector.sport;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 	}
@@ -1663,7 +1658,7 @@
 	if (xp->family == AF_INET) {
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
-		sin->sin_addr.s_addr = xp->selector.daddr.xfrm4_addr;
+		sin->sin_addr.s_addr = xp->selector.daddr.a4;
 		sin->sin_port = xp->selector.dport;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 	}
@@ -1751,12 +1746,12 @@
 			case AF_INET:
 				sin = (void*)(rq+1);
 				sin->sin_family = AF_INET;
-				sin->sin_addr.s_addr = t->saddr.xfrm4_addr;
+				sin->sin_addr.s_addr = t->saddr.a4;
 				sin->sin_port = 0;
 				memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 				sin++;
 				sin->sin_family = AF_INET;
-				sin->sin_addr.s_addr = t->id.daddr.xfrm4_addr;
+				sin->sin_addr.s_addr = t->id.daddr.a4;
 				sin->sin_port = 0;
 				memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 				break;
@@ -2340,7 +2335,7 @@
 
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
-		sin->sin_addr.s_addr = x->props.saddr.xfrm4_addr;
+		sin->sin_addr.s_addr = x->props.saddr.a4;
 		sin->sin_port = 0;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 	}
@@ -2374,7 +2369,7 @@
 
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
-		sin->sin_addr.s_addr = x->id.daddr.xfrm4_addr;
+		sin->sin_addr.s_addr = x->id.daddr.a4;
 		sin->sin_port = 0;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 	}
@@ -2416,8 +2411,23 @@
 	struct xfrm_policy *xp;
 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
 
-	if (opt != IP_IPSEC_POLICY) {
-		*dir = -EOPNOTSUPP;
+	switch (family) {
+	case AF_INET:
+		if (opt != IP_IPSEC_POLICY) {
+			*dir = -EOPNOTSUPP;
+			return NULL;
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		if (opt != IPV6_IPSEC_POLICY) {
+			*dir = -EOPNOTSUPP;
+			return NULL;
+		}
+		break;
+#endif
+	default:
+		*dir = -EINVAL;
 		return NULL;
 	}
 
diff -urN linux-2.5.65-bk4/net/netlink/netlink_dev.c linux-2.5.65-bk5/net/netlink/netlink_dev.c
--- linux-2.5.65-bk4/net/netlink/netlink_dev.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/net/netlink/netlink_dev.c	Mon Mar 31 12:44:34 2003
@@ -198,7 +198,7 @@
 		printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
 		return -EIO;
 	}
-	devfs_mk_dir (NULL, "netlink", NULL);
+	devfs_mk_dir("netlink");
 	/*  Someone tell me the official names for the uppercase ones  */
 	for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) {
 		char name[20];
diff -urN linux-2.5.65-bk4/net/netsyms.c linux-2.5.65-bk5/net/netsyms.c
--- linux-2.5.65-bk4/net/netsyms.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/netsyms.c	Mon Mar 31 12:44:34 2003
@@ -292,6 +292,7 @@
 EXPORT_SYMBOL(dlci_ioctl_hook);
 #endif
 
+EXPORT_SYMBOL(xfrm_user_policy);
 EXPORT_SYMBOL(km_waitq);
 EXPORT_SYMBOL(xfrm_cfg_sem);
 EXPORT_SYMBOL(xfrm_policy_alloc);
@@ -302,14 +303,20 @@
 EXPORT_SYMBOL(__xfrm_route_forward);
 EXPORT_SYMBOL(xfrm_state_alloc);
 EXPORT_SYMBOL(__xfrm_state_destroy);
-EXPORT_SYMBOL(xfrm4_state_find);
+EXPORT_SYMBOL(xfrm_state_find);
 EXPORT_SYMBOL(xfrm_state_insert);
 EXPORT_SYMBOL(xfrm_state_check_expire);
 EXPORT_SYMBOL(xfrm_state_check_space);
-EXPORT_SYMBOL(xfrm4_state_lookup);
+EXPORT_SYMBOL(xfrm_state_lookup);
+EXPORT_SYMBOL(xfrm_state_register_afinfo);
+EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
+EXPORT_SYMBOL(xfrm_state_get_afinfo);
+EXPORT_SYMBOL(xfrm_state_put_afinfo);
 EXPORT_SYMBOL(xfrm_replay_check);
 EXPORT_SYMBOL(xfrm_replay_advance);
 EXPORT_SYMBOL(xfrm_check_selectors);
+EXPORT_SYMBOL(__secpath_destroy);
+EXPORT_SYMBOL(xfrm_parse_spi);
 EXPORT_SYMBOL(xfrm4_rcv);
 EXPORT_SYMBOL(xfrm_register_type);
 EXPORT_SYMBOL(xfrm_unregister_type);
@@ -330,28 +337,24 @@
 EXPORT_SYMBOL(xfrm_policy_flush);
 EXPORT_SYMBOL(xfrm_policy_byid);
 EXPORT_SYMBOL(xfrm_policy_list);
-EXPORT_SYMBOL(xfrm_dst_lookup_register);
-EXPORT_SYMBOL(xfrm_dst_lookup_unregister);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-EXPORT_SYMBOL(xfrm6_state_find);
-EXPORT_SYMBOL(xfrm6_rcv);
-EXPORT_SYMBOL(xfrm6_state_lookup);
-EXPORT_SYMBOL(xfrm6_find_acq);
-EXPORT_SYMBOL(xfrm6_register_type);
-EXPORT_SYMBOL(xfrm6_unregister_type);
-EXPORT_SYMBOL(xfrm6_get_type);
-EXPORT_SYMBOL(xfrm6_clear_mutable_options);
-#endif
+EXPORT_SYMBOL(xfrm_dst_lookup);
+EXPORT_SYMBOL(xfrm_policy_register_afinfo);
+EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
+EXPORT_SYMBOL(xfrm_policy_get_afinfo);
+EXPORT_SYMBOL(xfrm_policy_put_afinfo);
 
 EXPORT_SYMBOL_GPL(xfrm_probe_algs);
 EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
 EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byidx);
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
 #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
 EXPORT_SYMBOL_GPL(skb_ah_walk);
 #endif
diff -urN linux-2.5.65-bk4/net/sctp/input.c linux-2.5.65-bk5/net/sctp/input.c
--- linux-2.5.65-bk4/net/sctp/input.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk5/net/sctp/input.c	Mon Mar 31 12:44:34 2003
@@ -110,6 +110,7 @@
 	struct sctphdr *sh;
 	union sctp_addr src;
 	union sctp_addr dest;
+	int family;
 	struct sctp_af *af;
 	int ret = 0;
 
@@ -129,7 +130,8 @@
 
 	skb_pull(skb, sizeof(struct sctphdr));	
 
-	af = sctp_get_af_specific(ipver2af(skb->nh.iph->version));
+	family = ipver2af(skb->nh.iph->version);
+	af = sctp_get_af_specific(family);
 	if (unlikely(!af)) 
 		goto bad_packet;
 
@@ -173,7 +175,7 @@
 	rcvr = asoc ? &asoc->base : &ep->base;
 	sk = rcvr->sk;
 
-	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb))
+	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
 		goto discard_release;
 
 	ret = sk_filter(sk, skb, 1);
diff -urN linux-2.5.65-bk4/net/sctp/ipv6.c linux-2.5.65-bk5/net/sctp/ipv6.c
--- linux-2.5.65-bk4/net/sctp/ipv6.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/net/sctp/ipv6.c	Mon Mar 31 12:44:34 2003
@@ -672,8 +672,13 @@
 	.flags         = SCTP_PROTOSW_FLAG
 };
 
+static int sctp6_rcv(struct sk_buff **pskb)
+{
+	return sctp_rcv(*pskb);
+}
+
 static struct inet6_protocol sctpv6_protocol = {
-	.handler      = sctp_rcv,
+	.handler      = sctp6_rcv,
 	.err_handler  = sctp_v6_err,
 };
 
diff -urN linux-2.5.65-bk4/net/socket.c linux-2.5.65-bk5/net/socket.c
--- linux-2.5.65-bk4/net/socket.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk5/net/socket.c	Mon Mar 31 12:44:34 2003
@@ -89,7 +89,7 @@
 #endif	/* CONFIG_NET_RADIO */
 
 #include <asm/uaccess.h>
-#include <net/compat_socket.h>
+#include <net/compat.h>
 
 #include <net/sock.h>
 #include <linux/netfilter.h>
@@ -1558,7 +1558,7 @@
 	
 	err = -EFAULT;
 	if (MSG_CMSG_COMPAT & flags) {
-		if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat))
+		if (get_compat_msghdr(&msg_sys, msg_compat))
 			return -EFAULT;
 	} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
 		return -EFAULT;
@@ -1652,7 +1652,7 @@
 	int *uaddr_len;
 	
 	if (MSG_CMSG_COMPAT & flags) {
-		if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat))
+		if (get_compat_msghdr(&msg_sys, msg_compat))
 			return -EFAULT;
 	} else
 		if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
@@ -1708,15 +1708,9 @@
 	err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg));
 	if (err)
 		goto out_freeiov;
-	if (MSG_CMSG_COMPAT & flags) {
-		unsigned long ucmsg_ptr;
-		compat_size_t uclen;
-		if((unsigned long) msg_sys.msg_control != cmsg_ptr)
-			cmsg_compat_recvmsg_fixup(&msg_sys, cmsg_ptr);
-		ucmsg_ptr = ((unsigned long)msg_sys.msg_control);
-		uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err = __put_user(uclen, &msg_compat->msg_controllen);
-	} else
+	if (MSG_CMSG_COMPAT & flags)
+		err = put_compat_msg_controllen(&msg_sys, msg_compat, cmsg_ptr);
+	else
 		err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
 				 &msg->msg_controllen);
 	if (err)
diff -urN linux-2.5.65-bk4/sound/core/Makefile linux-2.5.65-bk5/sound/core/Makefile
--- linux-2.5.65-bk4/sound/core/Makefile	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/sound/core/Makefile	Mon Mar 31 12:44:34 2003
@@ -95,6 +95,7 @@
 obj-$(CONFIG_SND_YMFPCI) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_POWERMAC) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
 obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_PC98_CS4232) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o snd-hwdep.o
 ifeq ($(CONFIG_SND_SB16_CSP),y)
   obj-$(CONFIG_SND_SB16) += snd-hwdep.o
   obj-$(CONFIG_SND_SBAWE) += snd-hwdep.o
diff -urN linux-2.5.65-bk4/sound/core/sound.c linux-2.5.65-bk5/sound/core/sound.c
--- linux-2.5.65-bk4/sound/core/sound.c	Mon Mar 31 12:44:30 2003
+++ linux-2.5.65-bk5/sound/core/sound.c	Mon Mar 31 12:44:34 2003
@@ -346,7 +346,7 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
 	devfs_handle = devfs_mk_dir(NULL, "snd", 3, NULL);
 #else
-	devfs_handle = devfs_mk_dir(NULL, "snd", NULL);
+	devfs_handle = devfs_mk_dir("snd");
 #endif
 #endif
 	if (register_chrdev(major, "alsa", &snd_fops)) {
diff -urN linux-2.5.65-bk4/sound/drivers/mpu401/Makefile linux-2.5.65-bk5/sound/drivers/mpu401/Makefile
--- linux-2.5.65-bk4/sound/drivers/mpu401/Makefile	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk5/sound/drivers/mpu401/Makefile	Mon Mar 31 12:44:34 2003
@@ -37,5 +37,6 @@
 obj-$(CONFIG_SND_ALI5451) += snd-mpu401-uart.o
 obj-$(CONFIG_SND_TRIDENT) += snd-mpu401-uart.o
 obj-$(CONFIG_SND_YMFPCI) += snd-mpu401-uart.o
+obj-$(CONFIG_SND_PC98_CS4232) += snd-mpu401-uart.o
 
 obj-m := $(sort $(obj-m))
diff -urN linux-2.5.65-bk4/sound/drivers/opl3/Makefile linux-2.5.65-bk5/sound/drivers/opl3/Makefile
--- linux-2.5.65-bk4/sound/drivers/opl3/Makefile	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk5/sound/drivers/opl3/Makefile	Mon Mar 31 12:44:34 2003
@@ -24,6 +24,7 @@
 obj-$(CONFIG_SND_OPL3SA2) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_AD1816A) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_CS4232) += $(OPL3_OBJS)
+obj-$(CONFIG_SND_PC98_CS4232) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_CS4236) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_ES1688) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_GUSEXTREME) += $(OPL3_OBJS)
diff -urN linux-2.5.65-bk4/sound/isa/Kconfig linux-2.5.65-bk5/sound/isa/Kconfig
--- linux-2.5.65-bk4/sound/isa/Kconfig	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk5/sound/isa/Kconfig	Mon Mar 31 12:44:34 2003
@@ -39,6 +39,12 @@
 	  Say 'Y' or 'M' to include support for CS4235,CS4236,CS4237B,CS4238B,CS4239
 	  chips from Cirrus Logic - Crystal Semiconductors.
 
+config SND_PC98_CS4232
+	tristate "NEC PC9800 CS4232 driver"
+	depends on SND
+	help
+	  Say 'Y' or 'M' to include support for NEC PC-9801/PC-9821 sound cards
+
 config SND_ES968
 	tristate "Generic ESS ES968 driver"
 	depends on SND && ISAPNP
diff -urN linux-2.5.65-bk4/sound/isa/cs423x/Makefile linux-2.5.65-bk5/sound/isa/cs423x/Makefile
--- linux-2.5.65-bk4/sound/isa/cs423x/Makefile	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk5/sound/isa/cs423x/Makefile	Mon Mar 31 12:44:34 2003
@@ -8,6 +8,7 @@
 snd-cs4231-objs := cs4231.o
 snd-cs4232-objs := cs4232.o
 snd-cs4236-objs := cs4236.o
+snd-pc98-cs4232-objs := pc98.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o
@@ -20,5 +21,6 @@
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-cs4231-lib.o
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o
 obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o
+obj-$(CONFIG_SND_PC98_CS4232) += snd-pc98-cs4232.o snd-cs4231-lib.o
 
 obj-m := $(sort $(obj-m))
diff -urN linux-2.5.65-bk4/sound/sound_core.c linux-2.5.65-bk5/sound/sound_core.c
--- linux-2.5.65-bk4/sound/sound_core.c	Mon Mar 17 13:44:48 2003
+++ linux-2.5.65-bk5/sound/sound_core.c	Mon Mar 31 12:44:34 2003
@@ -567,7 +567,7 @@
 		printk(KERN_ERR "soundcore: sound device already in use.\n");
 		return -EBUSY;
 	}
-	devfs_mk_dir (NULL, "sound", NULL);
+	devfs_mk_dir ("sound");
 
 	return 0;
 }
