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

diff -urN linux-2.5.69-bk14/Documentation/networking/ip-sysctl.txt linux-2.5.69-bk15/Documentation/networking/ip-sysctl.txt
--- linux-2.5.69-bk14/Documentation/networking/ip-sysctl.txt	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/Documentation/networking/ip-sysctl.txt	2003-05-21 04:47:28.000000000 -0700
@@ -613,12 +613,6 @@
 	routers are present.
 	Default: 3
 
-icmp/*:
-ratelimit - INTEGER
-	Limit the maximal rates for sending ICMPv6 packets.
-	0 to disable any limiting, otherwise the maximal rate in jiffies(1)
-	Default: 100
-
 use_tempaddr - INTEGER
 	Preference for Privacy Extensions (RFC3041).
 	  <= 0 : disable Privacy Extensions
@@ -649,6 +643,12 @@
 	valid temporary addresses.
 	Default: 5
 
+icmp/*:
+ratelimit - INTEGER
+	Limit the maximal rates for sending ICMPv6 packets.
+	0 to disable any limiting, otherwise the maximal rate in jiffies(1)
+	Default: 100
+
 
 IPv6 Update by:
 Pekka Savola <pekkas@netcore.fi>
diff -urN linux-2.5.69-bk14/Makefile linux-2.5.69-bk15/Makefile
--- linux-2.5.69-bk14/Makefile	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/Makefile	2003-05-21 04:47:29.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 69
-EXTRAVERSION = -bk14
+EXTRAVERSION = -bk15
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.69-bk14/arch/alpha/kernel/process.c linux-2.5.69-bk15/arch/alpha/kernel/process.c
--- linux-2.5.69-bk14/arch/alpha/kernel/process.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/arch/alpha/kernel/process.c	2003-05-21 04:47:29.000000000 -0700
@@ -235,23 +235,18 @@
 alpha_clone(unsigned long clone_flags, unsigned long usp, int *parent_tid,
 	    int *child_tid, unsigned long tls_value, struct pt_regs *regs)
 {
-	struct task_struct *p;
-
 	if (!usp)
 		usp = rdusp();
 
-	p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
-		    parent_tid, child_tid);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
+		       parent_tid, child_tid);
 }
 
 int
 alpha_vfork(struct pt_regs *regs)
 {
-	struct task_struct *p;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
-		    regs, 0, NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
+		       regs, 0, NULL, NULL);
 }
 
 /*
diff -urN linux-2.5.69-bk14/arch/alpha/kernel/ptrace.c linux-2.5.69-bk15/arch/alpha/kernel/ptrace.c
--- linux-2.5.69-bk14/arch/alpha/kernel/ptrace.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/arch/alpha/kernel/ptrace.c	2003-05-21 04:47:29.000000000 -0700
@@ -366,8 +366,8 @@
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		/* Mark single stepping.  */
-		child->thread_info->bpt_nsaved = -1;
+		/* Set single stepping.  */
+		ptrace_set_bpt(child);
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		wake_up_process(child);
 		child->exit_code = data;
@@ -397,11 +397,11 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	/* The 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
+
 	/*
 	 * This isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff -urN linux-2.5.69-bk14/arch/alpha/kernel/smp.c linux-2.5.69-bk15/arch/alpha/kernel/smp.c
--- linux-2.5.69-bk14/arch/alpha/kernel/smp.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/arch/alpha/kernel/smp.c	2003-05-21 04:47:29.000000000 -0700
@@ -417,7 +417,12 @@
 	/* Don't care about the contents of regs since we'll never
 	   reschedule the forked task. */
 	struct pt_regs regs;
-	return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	int pid;
+	pid = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	if (pid < 0)
+		return NULL;
+
+	return find_task_by_pid (pid);
 }
 
 /*
@@ -436,7 +441,7 @@
 	   wish.  We can't use kernel_thread since we must avoid
 	   rescheduling the child.  */
 	idle = fork_by_hand();
-	if (IS_ERR(idle))
+	if (!idle)
 		panic("failed fork for CPU %d", cpuid);
 
 	init_idle(idle, cpuid);
diff -urN linux-2.5.69-bk14/arch/arm/kernel/sys_arm.c linux-2.5.69-bk15/arch/arm/kernel/sys_arm.c
--- linux-2.5.69-bk14/arch/arm/kernel/sys_arm.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk15/arch/arm/kernel/sys_arm.c	2003-05-21 04:47:29.000000000 -0700
@@ -238,9 +238,7 @@
  */
 asmlinkage int sys_fork(struct pt_regs *regs)
 {
-	struct task_struct *p;
-	p = do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
 }
 
 /* Clone a task - this clones the calling program thread.
@@ -248,8 +246,6 @@
  */
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs)
 {
-	struct task_struct *p;
-
 	/*
 	 * We don't support SETTID / CLEARTID
 	 */
@@ -259,16 +255,12 @@
 	if (!newsp)
 		newsp = regs->ARM_sp;
 
-	p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
-
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
 {
-	struct task_struct *p;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
 }
 
 /* sys_execve() executes a new program.
diff -urN linux-2.5.69-bk14/arch/i386/kernel/setup.c linux-2.5.69-bk15/arch/i386/kernel/setup.c
--- linux-2.5.69-bk14/arch/i386/kernel/setup.c	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/arch/i386/kernel/setup.c	2003-05-21 04:47:29.000000000 -0700
@@ -799,13 +799,13 @@
 /* Use inline assembly to define this because the nops are defined 
    as inline assembly strings in the include files and we cannot 
    get them easily into strings. */
-asm("intelnops: " 
+asm("\t.data\nintelnops: " 
     GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
     GENERIC_NOP7 GENERIC_NOP8); 
-asm("k8nops: " 
+asm("\t.data\nk8nops: " 
     K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
     K8_NOP7 K8_NOP8); 
-asm("k7nops: " 
+asm("\t.data\nk7nops: " 
     K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
     K7_NOP7 K7_NOP8); 
     
diff -urN linux-2.5.69-bk14/arch/i386/mach-voyager/voyager_smp.c linux-2.5.69-bk15/arch/i386/mach-voyager/voyager_smp.c
--- linux-2.5.69-bk14/arch/i386/mach-voyager/voyager_smp.c	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/arch/i386/mach-voyager/voyager_smp.c	2003-05-21 04:47:29.000000000 -0700
@@ -593,6 +593,8 @@
 	if(IS_ERR(idle))
 		panic("failed fork for CPU%d", cpu);
 
+	wake_up_forked_process(idle);
+
 	init_idle(idle, cpu);
 
 	idle->thread.eip = (unsigned long) start_secondary;
diff -urN linux-2.5.69-bk14/arch/ppc/kernel/process.c linux-2.5.69-bk15/arch/ppc/kernel/process.c
--- linux-2.5.69-bk14/arch/ppc/kernel/process.c	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/arch/ppc/kernel/process.c	2003-05-21 04:47:30.000000000 -0700
@@ -445,33 +445,26 @@
 	      void *child_threadptr, int *child_tidp, int p6,
 	      struct pt_regs *regs)
 {
- 	struct task_struct *p;
-
 	CHECK_FULL_REGS(regs);
 	if (usp == 0)
 		usp = regs->gpr[1];	/* stack pointer for child */
- 	p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
-		    parent_tidp, child_tidp);
- 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+ 	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
+			parent_tidp, child_tidp);
 }
 
 int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
 	     struct pt_regs *regs)
 {
-	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
-	p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
 }
 
 int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
 	      struct pt_regs *regs)
 {
-	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs,
-		    0, NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
+			regs, 0, NULL, NULL);
 }
 
 int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
diff -urN linux-2.5.69-bk14/arch/ppc/kernel/smp.c linux-2.5.69-bk15/arch/ppc/kernel/smp.c
--- linux-2.5.69-bk14/arch/ppc/kernel/smp.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/arch/ppc/kernel/smp.c	2003-05-21 04:47:30.000000000 -0700
@@ -403,7 +403,7 @@
 	/* create a process for the processor */
 	/* only regs.msr is actually used, and 0 is OK for it */
 	memset(&regs, 0, sizeof(struct pt_regs));
-	p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
 
diff -urN linux-2.5.69-bk14/arch/ppc64/kernel/ioctl32.c linux-2.5.69-bk15/arch/ppc64/kernel/ioctl32.c
--- linux-2.5.69-bk14/arch/ppc64/kernel/ioctl32.c	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/arch/ppc64/kernel/ioctl32.c	2003-05-21 04:47:30.000000000 -0700
@@ -672,21 +672,6 @@
 	return err;
 }
 
-static inline void *alloc_user_space(long len)
-{
-	struct pt_regs *regs = current->thread.regs;
-	unsigned long usp = regs->gpr[1];
-
-	/*
-	 * We cant access below the stack pointer in the 32bit ABI and
-	 * can access 288 bytes in the 64bit ABI
-	 */
-	if (!(test_thread_flag(TIF_32BIT)))
-		usp -= 288;
-
-	return (void *) (usp - len);
-}
-
 int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq *u_ifreq64;
@@ -702,7 +687,7 @@
 		return -EFAULT;
 	data64 = A(data32);
 
-	u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
+	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 
 	/* Don't check these user accesses, just let that get trapped
 	 * in the ioctl handler instead.
diff -urN linux-2.5.69-bk14/arch/ppc64/kernel/process.c linux-2.5.69-bk15/arch/ppc64/kernel/process.c
--- linux-2.5.69-bk14/arch/ppc64/kernel/process.c	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/arch/ppc64/kernel/process.c	2003-05-21 04:47:30.000000000 -0700
@@ -300,7 +300,6 @@
 	      unsigned long p4, unsigned long p5, unsigned long p6,
 	      struct pt_regs *regs)
 {
-	struct task_struct *p;
 	unsigned long parent_tidptr = 0;
 	unsigned long child_tidptr = 0;
 
@@ -320,36 +319,29 @@
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
 
-	p = do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0,
+	return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0,
 		    (int *)parent_tidptr, (int *)child_tidptr);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
 	     unsigned long p4, unsigned long p5, unsigned long p6,
 	     struct pt_regs *regs)
 {
-	struct task_struct *p;
-
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
 
-	p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
 }
 
 int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
 	      unsigned long p4, unsigned long p5, unsigned long p6,
 	      struct pt_regs *regs)
 {
-	struct task_struct *p;
-
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
 
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0,
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0,
 	            NULL, NULL);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
diff -urN linux-2.5.69-bk14/arch/ppc64/kernel/smp.c linux-2.5.69-bk15/arch/ppc64/kernel/smp.c
--- linux-2.5.69-bk14/arch/ppc64/kernel/smp.c	2003-05-21 04:47:23.000000000 -0700
+++ linux-2.5.69-bk15/arch/ppc64/kernel/smp.c	2003-05-21 04:47:30.000000000 -0700
@@ -610,10 +610,11 @@
 	/* create a process for the processor */
 	/* only regs.msr is actually used, and 0 is OK for it */
 	memset(&regs, 0, sizeof(struct pt_regs));
-	p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
 
+	wake_up_forked_process(p);
 	init_idle(p, cpu);
 	unhash_process(p);
 
diff -urN linux-2.5.69-bk14/arch/sparc64/kernel/ioctl32.c linux-2.5.69-bk15/arch/sparc64/kernel/ioctl32.c
--- linux-2.5.69-bk14/arch/sparc64/kernel/ioctl32.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/arch/sparc64/kernel/ioctl32.c	2003-05-21 04:47:30.000000000 -0700
@@ -659,17 +659,6 @@
 	return err;
 }
 
-static __inline__ void *alloc_user_space(long len)
-{
-	struct pt_regs *regs = current_thread_info()->kregs;
-	unsigned long usp = regs->u_regs[UREG_I6];
-
-	if (!(test_thread_flag(TIF_32BIT)))
-		usp += STACK_BIAS;
-
-	return (void *) (usp - len);
-}
-
 int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq *u_ifreq64;
@@ -685,7 +674,7 @@
 		return -EFAULT;
 	data64 = A(data32);
 
-	u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
+	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 
 	/* Don't check these user accesses, just let that get trapped
 	 * in the ioctl handler instead.
@@ -1701,7 +1690,7 @@
 static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
-	struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog));
+	struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
 	void __user *fptr64;
 	u32 fptr32;
 	u16 flen;
diff -urN linux-2.5.69-bk14/arch/x86_64/ia32/ia32_ioctl.c linux-2.5.69-bk15/arch/x86_64/ia32/ia32_ioctl.c
--- linux-2.5.69-bk14/arch/x86_64/ia32/ia32_ioctl.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk15/arch/x86_64/ia32/ia32_ioctl.c	2003-05-21 04:47:31.000000000 -0700
@@ -671,12 +671,6 @@
 	return err;
 }
 
-static __inline__ void *alloc_user_space(long len)
-{
-	struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs); 
-	return (void *)regs->rsp - len; 
-}
-
 int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq *u_ifreq64;
@@ -692,7 +686,7 @@
 		return -EFAULT;
 	data64 = (void *) A(data32);
 
-	u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
+	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 
 	/* Don't check these user accesses, just let that get trapped
 	 * in the ioctl handler instead.
@@ -1573,7 +1567,7 @@
 static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
-	struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog));
+	struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
 	void *fptr64;
 	u32 fptr32;
 	u16 flen;
diff -urN linux-2.5.69-bk14/drivers/net/3c59x.c linux-2.5.69-bk15/drivers/net/3c59x.c
--- linux-2.5.69-bk14/drivers/net/3c59x.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/3c59x.c	2003-05-21 04:47:33.000000000 -0700
@@ -1115,6 +1115,7 @@
 		goto out;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, gendev);
 	vp = dev->priv;
 
 	option = global_options;
diff -urN linux-2.5.69-bk14/drivers/net/8139cp.c linux-2.5.69-bk15/drivers/net/8139cp.c
--- linux-2.5.69-bk14/drivers/net/8139cp.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/8139cp.c	2003-05-21 04:47:33.000000000 -0700
@@ -1801,6 +1801,8 @@
 	if (!dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
 	cp = dev->priv;
 	cp->pdev = pdev;
 	cp->board_type = board_type;
diff -urN linux-2.5.69-bk14/drivers/net/8139too.c linux-2.5.69-bk15/drivers/net/8139too.c
--- linux-2.5.69-bk14/drivers/net/8139too.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/8139too.c	2003-05-21 04:47:33.000000000 -0700
@@ -768,6 +768,8 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
 	tp = dev->priv;
 	tp->pci_dev = pdev;
 
diff -urN linux-2.5.69-bk14/drivers/net/Makefile linux-2.5.69-bk15/drivers/net/Makefile
--- linux-2.5.69-bk14/drivers/net/Makefile	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/Makefile	2003-05-21 04:47:33.000000000 -0700
@@ -24,7 +24,7 @@
 obj-$(CONFIG_SUNQE) += sunqe.o
 obj-$(CONFIG_SUNBMAC) += sunbmac.o
 obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
-obj-$(CONFIG_SUNGEM) += sungem.o
+obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
 
 obj-$(CONFIG_MACE) += mace.o
 obj-$(CONFIG_BMAC) += bmac.o
diff -urN linux-2.5.69-bk14/drivers/net/Space.c linux-2.5.69-bk15/drivers/net/Space.c
--- linux-2.5.69-bk14/drivers/net/Space.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/Space.c	2003-05-21 04:47:33.000000000 -0700
@@ -131,26 +131,20 @@
 {
 	struct devprobe *p = plist;
 	unsigned long base_addr = dev->base_addr;
-#ifdef CONFIG_NET_DIVERT
 	int ret;
-#endif /* CONFIG_NET_DIVERT */
 
 	while (p->probe != NULL) {
 		if (base_addr && p->probe(dev) == 0) {	/* probe given addr */
-#ifdef CONFIG_NET_DIVERT
 			ret = alloc_divert_blk(dev);
 			if (ret)
 				return ret;
-#endif /* CONFIG_NET_DIVERT */
 			return 0;
 		} else if (p->status == 0) {		/* has autoprobe failed yet? */
 			p->status = p->probe(dev);	/* no, try autoprobe */
 			if (p->status == 0) {
-#ifdef CONFIG_NET_DIVERT
 				ret = alloc_divert_blk(dev);
 				if (ret)
 					return ret;
-#endif /* CONFIG_NET_DIVERT */
 				return 0;
 			}
 		}
diff -urN linux-2.5.69-bk14/drivers/net/acenic.c linux-2.5.69-bk15/drivers/net/acenic.c
--- linux-2.5.69-bk14/drivers/net/acenic.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/acenic.c	2003-05-21 04:47:33.000000000 -0700
@@ -188,6 +188,9 @@
 #define ACE_MOD_DEC_USE_COUNT		do{} while(0)
 #endif
 
+#ifndef SET_NETDEV_DEV
+#define SET_NETDEV_DEV(net, pdev)	do{} while(0)
+#endif
 
 #if LINUX_VERSION_CODE >= 0x2051c
 #define ace_sync_irq(irq)	synchronize_irq(irq)
@@ -651,6 +654,7 @@
 		}
 
 		SET_MODULE_OWNER(dev);
+		SET_NETDEV_DEV(dev, &pdev->dev);
 
 		if (!dev->priv)
 			dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
@@ -2428,7 +2432,7 @@
 }
 
 
-static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -2446,7 +2450,7 @@
 	 * spending any time in here.
 	 */
 	if (!(readl(&regs->HostCtrl) & IN_INT))
-		return;
+		return IRQ_NONE;
 
 	/*
 	 * ACK intr now. Otherwise we will lose updates to rx_ret_prd,
@@ -2552,6 +2556,8 @@
 			tasklet_schedule(&ap->ace_tasklet);
 		}
 	}
+
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk14/drivers/net/acenic.h linux-2.5.69-bk15/drivers/net/acenic.h
--- linux-2.5.69-bk14/drivers/net/acenic.h	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/acenic.h	2003-05-21 04:47:33.000000000 -0700
@@ -781,7 +781,7 @@
 static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs);
 static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs);
 static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs);
-static void ace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int ace_load_firmware(struct net_device *dev);
 static int ace_open(struct net_device *dev);
 static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev);
diff -urN linux-2.5.69-bk14/drivers/net/amd8111e.c linux-2.5.69-bk15/drivers/net/amd8111e.c
--- linux-2.5.69-bk14/drivers/net/amd8111e.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/amd8111e.c	2003-05-21 04:47:33.000000000 -0700
@@ -1542,6 +1542,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 #if AMD8111E_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ;
diff -urN linux-2.5.69-bk14/drivers/net/defxx.c linux-2.5.69-bk15/drivers/net/defxx.c
--- linux-2.5.69-bk14/drivers/net/defxx.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/defxx.c	2003-05-21 04:47:33.000000000 -0700
@@ -443,6 +443,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	bp = dev->priv;
 
diff -urN linux-2.5.69-bk14/drivers/net/dl2k.c linux-2.5.69-bk15/drivers/net/dl2k.c
--- linux-2.5.69-bk14/drivers/net/dl2k.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/dl2k.c	2003-05-21 04:47:33.000000000 -0700
@@ -154,6 +154,7 @@
 		goto err_out_res;
 	}
 	SET_MODULE_OWNER (dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 #ifdef MEM_MAPPING
 	ioaddr = pci_resource_start (pdev, 1);
diff -urN linux-2.5.69-bk14/drivers/net/e100/e100_main.c linux-2.5.69-bk15/drivers/net/e100/e100_main.c
--- linux-2.5.69-bk14/drivers/net/e100/e100_main.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/e100/e100_main.c	2003-05-21 04:47:33.000000000 -0700
@@ -591,6 +591,7 @@
 	bdp->device = dev;
 
 	pci_set_drvdata(pcid, dev);
+	SET_NETDEV_DEV(dev, &pcid->dev);
 
 	if ((rc = e100_alloc_space(bdp)) != 0) {
 		goto err_dev;
diff -urN linux-2.5.69-bk14/drivers/net/e1000/e1000_main.c linux-2.5.69-bk15/drivers/net/e1000/e1000_main.c
--- linux-2.5.69-bk14/drivers/net/e1000/e1000_main.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/e1000/e1000_main.c	2003-05-21 04:47:33.000000000 -0700
@@ -391,6 +391,7 @@
 		goto err_alloc_etherdev;
 
 	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	pci_set_drvdata(pdev, netdev);
 	adapter = netdev->priv;
diff -urN linux-2.5.69-bk14/drivers/net/eepro100.c linux-2.5.69-bk15/drivers/net/eepro100.c
--- linux-2.5.69-bk14/drivers/net/eepro100.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/eepro100.c	2003-05-21 04:47:33.000000000 -0700
@@ -678,6 +678,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (dev->mem_start > 0)
 		option = dev->mem_start;
@@ -829,6 +830,7 @@
 	pci_set_power_state(pdev, acpi_idle_state);
 
 	pci_set_drvdata (pdev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	dev->irq = pdev->irq;
 
diff -urN linux-2.5.69-bk14/drivers/net/epic100.c linux-2.5.69-bk15/drivers/net/epic100.c
--- linux-2.5.69-bk14/drivers/net/epic100.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/epic100.c	2003-05-21 04:47:33.000000000 -0700
@@ -409,6 +409,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_free_netdev;
diff -urN linux-2.5.69-bk14/drivers/net/fealnx.c linux-2.5.69-bk15/drivers/net/fealnx.c
--- linux-2.5.69-bk14/drivers/net/fealnx.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/fealnx.c	2003-05-21 04:47:33.000000000 -0700
@@ -539,6 +539,7 @@
 		goto err_out_unmap;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	/* read ethernet id */
 	for (i = 0; i < 6; ++i)
diff -urN linux-2.5.69-bk14/drivers/net/hamachi.c linux-2.5.69-bk15/drivers/net/hamachi.c
--- linux-2.5.69-bk14/drivers/net/hamachi.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/hamachi.c	2003-05-21 04:47:33.000000000 -0700
@@ -613,6 +613,7 @@
 		goto err_out_iounmap;
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 #ifdef TX_CHECKSUM
 	printk("check that skbcopy in ip_queue_xmit isn't happening\n");
diff -urN linux-2.5.69-bk14/drivers/net/hamradio/dmascc.c linux-2.5.69-bk15/drivers/net/hamradio/dmascc.c
--- linux-2.5.69-bk14/drivers/net/hamradio/dmascc.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/hamradio/dmascc.c	2003-05-21 04:47:33.000000000 -0700
@@ -324,10 +324,11 @@
 
     /* Unregister devices */
     for (i = 0; i < 2; i++) {
-      if (info->dev[i].name)
+      if (info->dev[i].name) {
 	rtnl_lock();
 	unregister_netdevice(&info->dev[i]);
 	rtnl_unlock();
+      }
     }
 
     /* Reset board */
diff -urN linux-2.5.69-bk14/drivers/net/hp100.c linux-2.5.69-bk15/drivers/net/hp100.c
--- linux-2.5.69-bk14/drivers/net/hp100.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/hp100.c	2003-05-21 04:47:33.000000000 -0700
@@ -776,6 +776,7 @@
 	hp100_clear_stats(lp, ioaddr);
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pci_dev->dev);
 	ether_setup(dev);
 
 	/* If busmaster mode is wanted, a dma-capable memory area is needed for
diff -urN linux-2.5.69-bk14/drivers/net/ioc3-eth.c linux-2.5.69-bk15/drivers/net/ioc3-eth.c
--- linux-2.5.69-bk14/drivers/net/ioc3-eth.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/ioc3-eth.c	2003-05-21 04:47:33.000000000 -0700
@@ -1532,6 +1532,8 @@
 		goto out_free;
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
 	ip = dev->priv;
 	ip->dev = dev;
 
diff -urN linux-2.5.69-bk14/drivers/net/ixgb/ixgb_main.c linux-2.5.69-bk15/drivers/net/ixgb/ixgb_main.c
--- linux-2.5.69-bk14/drivers/net/ixgb/ixgb_main.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/ixgb/ixgb_main.c	2003-05-21 04:47:33.000000000 -0700
@@ -333,6 +333,7 @@
 	}
 
 	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	pci_set_drvdata(pdev, netdev);
 	adapter = netdev->priv;
diff -urN linux-2.5.69-bk14/drivers/net/natsemi.c linux-2.5.69-bk15/drivers/net/natsemi.c
--- linux-2.5.69-bk14/drivers/net/natsemi.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/natsemi.c	2003-05-21 04:47:33.000000000 -0700
@@ -762,6 +762,7 @@
 	if (!dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	i = pci_request_regions(pdev, dev->name);
 	if (i) {
diff -urN linux-2.5.69-bk14/drivers/net/ne2k-pci.c linux-2.5.69-bk15/drivers/net/ne2k-pci.c
--- linux-2.5.69-bk14/drivers/net/ne2k-pci.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/ne2k-pci.c	2003-05-21 04:47:33.000000000 -0700
@@ -265,6 +265,7 @@
 		goto err_out_free_res;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	/* Reset card. Who knows what dain-bramaged state it was left in. */
 	{
diff -urN linux-2.5.69-bk14/drivers/net/ns83820.c linux-2.5.69-bk15/drivers/net/ns83820.c
--- linux-2.5.69-bk14/drivers/net/ns83820.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/ns83820.c	2003-05-21 04:47:33.000000000 -0700
@@ -1586,6 +1586,7 @@
 	dprintk("%s: done %s in %d loops\n", dev->net_dev.name, name, loops);
 }
 
+#ifdef PHY_CODE_IS_FINISHED
 static void ns83820_mii_write_bit(struct ns83820 *dev, int bit)
 {
 	/* drive MDC low */
@@ -1758,6 +1759,7 @@
 		dprintk("version: 0x%04x 0x%04x\n", a, b);
 	}
 }
+#endif
 
 static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
@@ -1788,7 +1790,8 @@
 
 	dev->ee.cache = &dev->MEAR_cache;
 	dev->ee.lock = &dev->misc_lock;
-	dev->net_dev.owner = THIS_MODULE;
+	SET_MODULE_OWNER(dev->net_dev);
+	SET_NETDEV_DEV(&dev->net_dev, &pci_dev->dev);
 	dev->net_dev.priv = dev;
 
 	INIT_WORK(&dev->tq_refill, queue_refill, dev);
diff -urN linux-2.5.69-bk14/drivers/net/pci-skeleton.c linux-2.5.69-bk15/drivers/net/pci-skeleton.c
--- linux-2.5.69-bk14/drivers/net/pci-skeleton.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/pci-skeleton.c	2003-05-21 04:47:33.000000000 -0700
@@ -610,6 +610,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	tp = dev->priv;
 
 	/* enable device (incl. PCI PM wakeup), and bus-mastering */
diff -urN linux-2.5.69-bk14/drivers/net/pcnet32.c linux-2.5.69-bk15/drivers/net/pcnet32.c
--- linux-2.5.69-bk14/drivers/net/pcnet32.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/pcnet32.c	2003-05-21 04:47:33.000000000 -0700
@@ -638,6 +638,7 @@
 	    release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	    return -ENOMEM;
     }
+    SET_NETDEV_DEV(dev, &pdev->dev);
 
     printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
 
@@ -718,6 +719,7 @@
     spin_lock_init(&lp->lock);
     
     SET_MODULE_OWNER(dev);
+    SET_NETDEV_DEV(dev, &pdev->dev);
     dev->priv = lp;
     lp->name = chipname;
     lp->shared_irq = shared;
diff -urN linux-2.5.69-bk14/drivers/net/ppp_generic.c linux-2.5.69-bk15/drivers/net/ppp_generic.c
--- linux-2.5.69-bk14/drivers/net/ppp_generic.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/ppp_generic.c	2003-05-21 04:47:33.000000000 -0700
@@ -2345,8 +2345,10 @@
 	ppp_unlock(ppp);
 	if (dev) {
 		rtnl_lock();
-		dev_close(dev);
+
+		/* This will call dev_close() for us. */
 		unregister_netdevice(dev);
+
 		rtnl_unlock();
 	}
 	cardmap_set(&all_ppp_units, ppp->file.index, NULL);
diff -urN linux-2.5.69-bk14/drivers/net/r8169.c linux-2.5.69-bk15/drivers/net/r8169.c
--- linux-2.5.69-bk14/drivers/net/r8169.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/r8169.c	2003-05-21 04:47:33.000000000 -0700
@@ -373,6 +373,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	tp = dev->priv;
 
 	// enable device (incl. PCI PM wakeup and hotplug setup)
diff -urN linux-2.5.69-bk14/drivers/net/rcpci45.c linux-2.5.69-bk15/drivers/net/rcpci45.c
--- linux-2.5.69-bk14/drivers/net/rcpci45.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/rcpci45.c	2003-05-21 04:47:33.000000000 -0700
@@ -179,6 +179,7 @@
 		goto err_out;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	error = pci_enable_device (pdev);
 	if (error) {
diff -urN linux-2.5.69-bk14/drivers/net/rrunner.c linux-2.5.69-bk15/drivers/net/rrunner.c
--- linux-2.5.69-bk14/drivers/net/rrunner.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/rrunner.c	2003-05-21 04:47:33.000000000 -0700
@@ -114,6 +114,7 @@
 	rrpriv = (struct rr_private *)dev->priv;
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_request_regions(pdev, "rrunner")) {
 		ret = -EIO;
diff -urN linux-2.5.69-bk14/drivers/net/sb1000.c linux-2.5.69-bk15/drivers/net/sb1000.c
--- linux-2.5.69-bk14/drivers/net/sb1000.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sb1000.c	2003-05-21 04:47:33.000000000 -0700
@@ -190,6 +190,7 @@
 	dev->flags = IFF_POINTOPOINT|IFF_NOARP;
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (sb1000_debug > 0)
 		printk(KERN_NOTICE "%s", version);
diff -urN linux-2.5.69-bk14/drivers/net/setup.c linux-2.5.69-bk15/drivers/net/setup.c
--- linux-2.5.69-bk14/drivers/net/setup.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/setup.c	2003-05-21 04:47:33.000000000 -0700
@@ -16,7 +16,6 @@
 extern int fec_enet_init(void); 
 extern int sdla_setup(void); 
 extern int sdla_c_setup(void); 
-extern int comx_init(void);
 extern int lmc_setup(void);
 
 extern int madgemc_probe(void);
@@ -52,10 +51,6 @@
 #if defined(CONFIG_FEC_ENET)
         {fec_enet_init, 0},
 #endif
-#if defined(CONFIG_COMX)
-	{comx_init, 0},
-#endif
-	 
 #if defined(CONFIG_LANMEDIA)
 	{lmc_setup, 0},
 #endif
diff -urN linux-2.5.69-bk14/drivers/net/sis900.c linux-2.5.69-bk15/drivers/net/sis900.c
--- linux-2.5.69-bk14/drivers/net/sis900.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sis900.c	2003-05-21 04:47:33.000000000 -0700
@@ -397,6 +397,7 @@
 	if (!net_dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(net_dev);
+	SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
 	/* We do a request_region() to register /proc/ioports info. */
 	ioaddr = pci_resource_start(pci_dev, 0);	
diff -urN linux-2.5.69-bk14/drivers/net/sk98lin/skge.c linux-2.5.69-bk15/drivers/net/sk98lin/skge.c
--- linux-2.5.69-bk14/drivers/net/sk98lin/skge.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sk98lin/skge.c	2003-05-21 04:47:33.000000000 -0700
@@ -460,6 +460,7 @@
 		dev->irq = pdev->irq;
 
 		SET_MODULE_OWNER(dev);
+		SET_NETDEV_DEV(dev, &pdev->dev);
 		dev->open =		&SkGeOpen;
 		dev->stop =		&SkGeClose;
 		dev->hard_start_xmit =	&SkGeXmit;
diff -urN linux-2.5.69-bk14/drivers/net/smc-mca.c linux-2.5.69-bk15/drivers/net/smc-mca.c
--- linux-2.5.69-bk14/drivers/net/smc-mca.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/smc-mca.c	2003-05-21 04:47:33.000000000 -0700
@@ -207,6 +207,7 @@
 		return -ENODEV;
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, gen_dev);
 
 	if((i = register_netdev(dev)) != 0)
 		return i;
diff -urN linux-2.5.69-bk14/drivers/net/starfire.c linux-2.5.69-bk15/drivers/net/starfire.c
--- linux-2.5.69-bk14/drivers/net/starfire.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/starfire.c	2003-05-21 04:47:33.000000000 -0700
@@ -876,6 +876,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	irq = pdev->irq;
 
diff -urN linux-2.5.69-bk14/drivers/net/sundance.c linux-2.5.69-bk15/drivers/net/sundance.c
--- linux-2.5.69-bk14/drivers/net/sundance.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sundance.c	2003-05-21 04:47:33.000000000 -0700
@@ -548,6 +548,7 @@
 	if (!dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_netdev;
diff -urN linux-2.5.69-bk14/drivers/net/sungem.c linux-2.5.69-bk15/drivers/net/sungem.c
--- linux-2.5.69-bk14/drivers/net/sungem.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sungem.c	2003-05-21 04:47:33.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: sungem.c,v 1.49 2002/01/23 15:40:45 davem Exp $
+/* $Id: sungem.c,v 1.44.2.22 2002/03/13 01:18:12 davem Exp $
  * sungem.c: Sun GEM ethernet driver.
  *
  * Copyright (C) 2000, 2001, 2002 David S. Miller (davem@redhat.com)
@@ -10,13 +10,8 @@
  *  - Get rid of all those nasty mdelay's and replace them
  * with schedule_timeout.
  *  - Implement WOL
- *  - Currently, forced Gb mode is only supported on bcm54xx
- *    PHY for which I use the SPD2 bit of the control register.
- *    On m1011 PHY, I can't force as I don't have the specs, but
- *    I can at least detect gigabit with autoneg.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -60,12 +55,20 @@
 #include <asm/pmac_feature.h>
 #endif
 
+#include "sungem_phy.h"
 #include "sungem.h"
 
+/* Stripping FCS is causing problems, disabled for now */
+#undef STRIP_FCS
+
 #define DEFAULT_MSG	(NETIF_MSG_DRV		| \
 			 NETIF_MSG_PROBE	| \
 			 NETIF_MSG_LINK)
 
+#define ADVERTISE_MASK	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+			 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
+
 #define DRV_NAME	"sungem"
 #define DRV_VERSION	"0.97"
 #define DRV_RELDATE	"3/20/02"
@@ -78,24 +81,6 @@
 MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(gem_debug, "i");
-MODULE_PARM_DESC(gem_debug, "bitmapped message enable number");
-MODULE_PARM(link_mode, "i");
-MODULE_PARM_DESC(link_mode, "default link mode");
-
-int gem_debug = -1;
-static int link_mode;
-
-static u16 link_modes[] __devinitdata = {
-	BMCR_ANENABLE,			/* 0 : autoneg */
-	0,				/* 1 : 10bt half duplex */
-	BMCR_SPEED100,			/* 2 : 100bt half duplex */
-	BMCR_SPD2, /* bcm54xx only */   /* 3 : 1000bt half duplex */
-	BMCR_FULLDPLX,			/* 4 : 10bt full duplex */
-	BMCR_SPEED100|BMCR_FULLDPLX,	/* 5 : 100bt full duplex */
-	BMCR_SPD2|BMCR_FULLDPLX		/* 6 : 1000bt full duplex */
-};
-
 #define GEM_MODULE_NAME	"gem"
 #define PFX GEM_MODULE_NAME ": "
 
@@ -116,12 +101,14 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMACP,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMAC2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{0, }
 };
 
 MODULE_DEVICE_TABLE(pci, gem_pci_tbl);
 
-static u16 __phy_read(struct gem *gp, int reg, int phy_addr)
+static u16 __phy_read(struct gem *gp, int phy_addr, int reg)
 {
 	u32 cmd;
 	int limit = 10000;
@@ -147,12 +134,18 @@
 	return cmd & MIF_FRAME_DATA;
 }
 
+static inline int _phy_read(struct net_device *dev, int mii_id, int reg)
+{
+	struct gem *gp = dev->priv;
+	return __phy_read(gp, mii_id, reg);
+}
+
 static inline u16 phy_read(struct gem *gp, int reg)
 {
-	return __phy_read(gp, reg, gp->mii_phy_addr);
+	return __phy_read(gp, gp->mii_phy_addr, reg);
 }
 
-static void __phy_write(struct gem *gp, int reg, u16 val, int phy_addr)
+static void __phy_write(struct gem *gp, int phy_addr, int reg, u16 val)
 {
 	u32 cmd;
 	int limit = 10000;
@@ -174,9 +167,15 @@
 	}
 }
 
+static inline void _phy_write(struct net_device *dev, int mii_id, int reg, int val)
+{
+	struct gem *gp = dev->priv;
+	__phy_write(gp, mii_id, reg, val & 0xffff);
+}
+
 static inline void phy_write(struct gem *gp, int reg, u16 val)
 {
-	__phy_write(gp, reg, val, gp->mii_phy_addr);
+	__phy_write(gp, gp->mii_phy_addr, reg, val);
 }
 
 static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
@@ -225,10 +224,11 @@
 	if (pcs_miistat & PCS_MIISTAT_LS) {
 		printk(KERN_INFO "%s: PCS link is now up.\n",
 		       dev->name);
+		netif_carrier_on(gp->dev);
 	} else {
 		printk(KERN_INFO "%s: PCS link is now down.\n",
 		       dev->name);
-
+		netif_carrier_off(gp->dev);
 		/* If this happens and the link timer is not running,
 		 * reset so we re-negotiate.
 		 */
@@ -1006,7 +1006,7 @@
 	} while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST));
 
 	if (limit <= 0)
-		printk(KERN_ERR "gem: SW reset is ghetto.\n");
+		printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
 }
 
 /* Must be invoked under gp->lock. */
@@ -1033,136 +1033,118 @@
 
 }
 
-/* Link modes of the BCM5400 PHY */
-static int phy_BCM5400_link_table[8][3] = {
-	{ 0, 0, 0 },	/* No link */
-	{ 0, 0, 0 },	/* 10BT Half Duplex */
-	{ 1, 0, 0 },	/* 10BT Full Duplex */
-	{ 0, 1, 0 },	/* 100BT Half Duplex */
-	{ 0, 1, 0 },	/* 100BT Half Duplex */
-	{ 1, 1, 0 },	/* 100BT Full Duplex*/
-	{ 1, 0, 1 },	/* 1000BT */
-	{ 1, 0, 1 },	/* 1000BT */
-};
 
 /* Must be invoked under gp->lock. */
+// XXX dbl check what that function should do when called on PCS PHY
 static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
 {
-	u16 ctl;
+	u32 advertise, features;
+	int autoneg;
+	int speed;
+	int duplex;
+
+	if (gp->phy_type != phy_mii_mdio0 &&
+     	    gp->phy_type != phy_mii_mdio1)
+     	    	goto non_mii;
+
+	/* Setup advertise */
+	if (found_mii_phy(gp))
+		features = gp->phy_mii.def->features;
+	else
+		features = 0;
+
+	advertise = features & ADVERTISE_MASK;
+	if (gp->phy_mii.advertising != 0)
+		advertise &= gp->phy_mii.advertising;
+
+	autoneg = gp->want_autoneg;
+	speed = gp->phy_mii.speed;
+	duplex = gp->phy_mii.duplex;
 	
 	/* Setup link parameters */
 	if (!ep)
 		goto start_aneg;
 	if (ep->autoneg == AUTONEG_ENABLE) {
-		/* TODO: parse ep->advertising */
-		gp->link_advertise |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
-		gp->link_advertise |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
-		/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
-		gp->link_cntl = BMCR_ANENABLE;
+		advertise = ep->advertising;
+		autoneg = 1;
 	} else {
-		gp->link_cntl = 0;
-		if (ep->speed == SPEED_100)
-			gp->link_cntl |= BMCR_SPEED100;
-		else if (ep->speed == SPEED_1000 && gp->gigabit_capable)
-			/* Hrm... check if this is right... */
-			gp->link_cntl |= BMCR_SPD2;
-		if (ep->duplex == DUPLEX_FULL)
-			gp->link_cntl |= BMCR_FULLDPLX;
+		autoneg = 0;
+		speed = ep->speed;
+		duplex = ep->duplex;
 	}
 
 start_aneg:
-	if (!gp->hw_running)
+	/* Sanitize settings based on PHY capabilities */
+	if ((features & SUPPORTED_Autoneg) == 0)
+		autoneg = 0;
+	if (speed == SPEED_1000 &&
+	    !(features & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)))
+		speed = SPEED_100;
+	if (speed == SPEED_100 &&
+	    !(features & (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full)))
+		speed = SPEED_10;
+	if (duplex == DUPLEX_FULL &&
+	    !(features & (SUPPORTED_1000baseT_Full |
+	    		  SUPPORTED_100baseT_Full |
+	    		  SUPPORTED_10baseT_Full)))
+	    	duplex = DUPLEX_HALF;
+	if (speed == 0)
+		speed = SPEED_10;
+	
+	/* If HW is down, we don't try to actually setup the PHY, we
+	 * just store the settings
+	 */
+	if (!gp->hw_running) {
+		gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
+		gp->phy_mii.speed = speed;
+		gp->phy_mii.duplex = duplex;
 		return;
+	}
 
 	/* Configure PHY & start aneg */
-	ctl = phy_read(gp, MII_BMCR);
-	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
-	ctl |= gp->link_cntl;
-	if (ctl & BMCR_ANENABLE) {
-		ctl |= BMCR_ANRESTART;
+	gp->want_autoneg = autoneg;
+	if (autoneg) {
+		if (found_mii_phy(gp))
+			gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, advertise);
 		gp->lstate = link_aneg;
 	} else {
+		if (found_mii_phy(gp))
+			gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, speed, duplex);
 		gp->lstate = link_force_ok;
 	}
-	phy_write(gp, MII_BMCR, ctl);
 
+non_mii:
 	gp->timer_ticks = 0;
 	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 }
 
-/* Must be invoked under gp->lock. */
-static void gem_read_mii_link_mode(struct gem *gp, int *fd, int *spd, int *pause)
-{
-	u32 val;
-
-	*fd = 0;
-	*spd = 10;
-	*pause = 0;
-	
-	if (gp->phy_mod == phymod_bcm5400 ||
-	    gp->phy_mod == phymod_bcm5401 ||
-	    gp->phy_mod == phymod_bcm5411) {
-		int link_mode;	
-
-	    	val = phy_read(gp, MII_BCM5400_AUXSTATUS);
-		link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
-			     MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
-		*fd = phy_BCM5400_link_table[link_mode][0];
-		*spd = phy_BCM5400_link_table[link_mode][2] ?
-			1000 :
-			(phy_BCM5400_link_table[link_mode][1] ? 100 : 10);
-		val = phy_read(gp, MII_LPA);
-		if (val & LPA_PAUSE)
-			*pause = 1;
-	} else {
-		val = phy_read(gp, MII_LPA);
-
-		if (val & (LPA_10FULL | LPA_100FULL))
-			*fd = 1;
-		if (val & (LPA_100FULL | LPA_100HALF))
-			*spd = 100;
-
-		if (gp->phy_mod == phymod_m1011) {
-			val = phy_read(gp, 0x0a);
-			if (val & 0xc00)
-				*spd = 1000;
-			if (val & 0x800)
-				*fd = 1;
-		}
-	}
-}
-
 /* A link-up condition has occurred, initialize and enable the
  * rest of the chip.
  *
  * Must be invoked under gp->lock.
  */
-static void gem_set_link_modes(struct gem *gp)
+static int gem_set_link_modes(struct gem *gp)
 {
 	u32 val;
 	int full_duplex, speed, pause;
 
 	full_duplex = 0;
-	speed = 10;
+	speed = SPEED_10;
 	pause = 0;
 
-	if (gp->phy_type == phy_mii_mdio0 ||
-	    gp->phy_type == phy_mii_mdio1) {
-		val = phy_read(gp, MII_BMCR);
-		if (val & BMCR_ANENABLE)
-			gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause);
-		else {
-			if (val & BMCR_FULLDPLX)
-				full_duplex = 1;
-			if (val & BMCR_SPEED100)
-				speed = 100;
-		}
-	} else {
+	if (found_mii_phy(gp)) {
+	    	if (gp->phy_mii.def->ops->read_link(&gp->phy_mii))
+	    		return 1;
+		full_duplex = (gp->phy_mii.duplex == DUPLEX_FULL);
+		speed = gp->phy_mii.speed;
+		pause = gp->phy_mii.pause;
+	} else if (gp->phy_type == phy_serialink ||
+	    	   gp->phy_type == phy_serdes) {
 		u32 pcs_lpa = readl(gp->regs + PCS_MIILP);
 
 		if (pcs_lpa & PCS_MIIADV_FD)
 			full_duplex = 1;
-		speed = 1000;
+		speed = SPEED_1000;
 	}
 
 	if (netif_msg_link(gp))
@@ -1186,7 +1168,7 @@
 		val |= MAC_XIFCFG_FLED;
 	}
 
-	if (speed == 1000)
+	if (speed == SPEED_1000)
 		val |= (MAC_XIFCFG_GMII);
 
 	writel(val, gp->regs + MAC_XIFCFG);
@@ -1194,7 +1176,7 @@
 	/* If gigabit and half-duplex, enable carrier extension
 	 * mode.  Else, disable it.
 	 */
-	if (speed == 1000 && !full_duplex) {
+	if (speed == SPEED_1000 && !full_duplex) {
 		val = readl(gp->regs + MAC_TXCFG);
 		writel(val | MAC_TXCFG_TCE, gp->regs + MAC_TXCFG);
 
@@ -1242,50 +1224,51 @@
 	writel(val, gp->regs + MAC_MCCFG);
 
 	gem_start_dma(gp);
+
+	return 0;
 }
 
 /* Must be invoked under gp->lock. */
 static int gem_mdio_link_not_up(struct gem *gp)
 {
-	u16 val;
-	
-	if (gp->lstate == link_force_ret) {
+	switch (gp->lstate) {
+	case link_force_ret:
 		if (netif_msg_link(gp))
 			printk(KERN_INFO "%s: Autoneg failed again, keeping"
 				" forced mode\n", gp->dev->name);
-		phy_write(gp, MII_BMCR, gp->link_fcntl);
+		gp->phy_mii.def->ops->setup_forced(&gp->phy_mii,
+			gp->last_forced_speed, DUPLEX_HALF);
 		gp->timer_ticks = 5;
 		gp->lstate = link_force_ok;
-	} else if (gp->lstate == link_aneg) {
-		val = phy_read(gp, MII_BMCR);
-
+		return 0;
+	case link_aneg:
 		if (netif_msg_link(gp))
 			printk(KERN_INFO "%s: switching to forced 100bt\n",
 				gp->dev->name);
 		/* Try forced modes. */
-		val &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
-		val &= ~(BMCR_FULLDPLX);
-		val |= BMCR_SPEED100;
-		phy_write(gp, MII_BMCR, val);
+		gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_100,
+			DUPLEX_HALF);
 		gp->timer_ticks = 5;
 		gp->lstate = link_force_try;
-	} else {
+		return 0;
+	case link_force_try:
 		/* Downgrade from 100 to 10 Mbps if necessary.
 		 * If already at 10Mbps, warn user about the
 		 * situation every 10 ticks.
 		 */
-		val = phy_read(gp, MII_BMCR);
-		if (val & BMCR_SPEED100) {
-			val &= ~BMCR_SPEED100;
-			phy_write(gp, MII_BMCR, val);
+		if (gp->phy_mii.speed == SPEED_100) {
+			gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_10,
+				DUPLEX_HALF);
 			gp->timer_ticks = 5;
 			if (netif_msg_link(gp))
 				printk(KERN_INFO "%s: switching to forced 10bt\n",
 					gp->dev->name);
+			return 0;
 		} else
 			return 1;
+	default:
+		return 0;
 	}
-	return 0;
 }
 
 static void gem_init_rings(struct gem *);
@@ -1325,7 +1308,8 @@
 static void gem_link_timer(unsigned long data)
 {
 	struct gem *gp = (struct gem *) data;
-
+	int restart_aneg = 0;
+		
 	if (!gp->hw_running)
 		return;
 
@@ -1337,62 +1321,8 @@
 	if (gp->reset_task_pending)
 		goto restart;
 	    	
-	if (gp->phy_type == phy_mii_mdio0 ||
-	    gp->phy_type == phy_mii_mdio1) {
-		u16 val = phy_read(gp, MII_BMSR);
-		u16 cntl = phy_read(gp, MII_BMCR);
-		int up;
-
-		/* When using autoneg, we really wait for ANEGCOMPLETE or we may
-		 * get a "transcient" incorrect link state
-		 */
-		if (cntl & BMCR_ANENABLE)
-			up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS);
-		else
-			up = (val & BMSR_LSTATUS) != 0;
-		if (up) {
-			/* Ok, here we got a link. If we had it due to a forced
-			 * fallback, and we were configured for autoneg, we do
-			 * retry a short autoneg pass. If you know your hub is
-			 * broken, use ethtool ;)
-			 */
-			if (gp->lstate == link_force_try && (gp->link_cntl & BMCR_ANENABLE)) {
-				gp->lstate = link_force_ret;
-				gp->link_fcntl = phy_read(gp, MII_BMCR);
-				gp->timer_ticks = 5;
-				if (netif_msg_link(gp))
-					printk(KERN_INFO "%s: Got link after fallback, retrying"
-						" autoneg once...\n", gp->dev->name);
-				phy_write(gp, MII_BMCR,
-					  gp->link_fcntl | BMCR_ANENABLE | BMCR_ANRESTART);
-			} else if (gp->lstate != link_up) {
-				gp->lstate = link_up;
-				if (gp->opened)
-					gem_set_link_modes(gp);
-			}
-		} else {
-			int restart = 0;
-
-			/* If the link was previously up, we restart the
-			 * whole process
-			 */
-			if (gp->lstate == link_up) {
-				gp->lstate = link_down;
-				if (netif_msg_link(gp))
-					printk(KERN_INFO "%s: Link down\n",
-						gp->dev->name);
-				gp->reset_task_pending = 2;
-				schedule_work(&gp->reset_task);
-				restart = 1;
-			} else if (++gp->timer_ticks > 10)
-				restart = gem_mdio_link_not_up(gp);
-
-			if (restart) {
-				gem_begin_auto_negotiation(gp, NULL);
-				goto out_unlock;
-			}
-		}
-	} else {
+	if (gp->phy_type == phy_serialink ||
+	    gp->phy_type == phy_serdes) {
 		u32 val = readl(gp->regs + PCS_MIISTAT);
 
 		if (!(val & PCS_MIISTAT_LS))
@@ -1400,11 +1330,56 @@
 
 		if ((val & PCS_MIISTAT_LS) != 0) {
 			gp->lstate = link_up;
+			netif_carrier_on(gp->dev);
 			if (gp->opened)
-				gem_set_link_modes(gp);
+				(void)gem_set_link_modes(gp);
 		}
+		goto restart;
+	}
+	if (found_mii_phy(gp) && gp->phy_mii.def->ops->poll_link(&gp->phy_mii)) {
+		/* Ok, here we got a link. If we had it due to a forced
+		 * fallback, and we were configured for autoneg, we do
+		 * retry a short autoneg pass. If you know your hub is
+		 * broken, use ethtool ;)
+		 */
+		if (gp->lstate == link_force_try && gp->want_autoneg) {
+			gp->lstate = link_force_ret;
+			gp->last_forced_speed = gp->phy_mii.speed;
+			gp->timer_ticks = 5;
+			if (netif_msg_link(gp))
+				printk(KERN_INFO "%s: Got link after fallback, retrying"
+					" autoneg once...\n", gp->dev->name);
+			gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
+		} else if (gp->lstate != link_up) {
+			gp->lstate = link_up;
+			netif_carrier_on(gp->dev);
+			if (gp->opened && gem_set_link_modes(gp))
+				restart_aneg = 1;
+		}
+	} else {
+		/* If the link was previously up, we restart the
+		 * whole process
+		 */
+		if (gp->lstate == link_up) {
+			gp->lstate = link_down;
+			if (netif_msg_link(gp))
+				printk(KERN_INFO "%s: Link down\n",
+					gp->dev->name);
+			netif_carrier_off(gp->dev);
+			gp->reset_task_pending = 2;
+			schedule_work(&gp->reset_task);
+			restart_aneg = 1;
+		} else if (++gp->timer_ticks > 10) {
+			if (found_mii_phy(gp))
+				restart_aneg = gem_mdio_link_not_up(gp);
+			else
+				restart_aneg = 1;
+		}
+	}
+	if (restart_aneg) {
+		gem_begin_auto_negotiation(gp, NULL);
+		goto out_unlock;
 	}
-
 restart:
 	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 out_unlock:
@@ -1507,150 +1482,10 @@
 }
 
 /* Must be invoked under gp->lock. */
-static int gem_reset_one_mii_phy(struct gem *gp, int phy_addr)
-{
-	u16 val;
-	int limit = 10000;
-	
-	val = __phy_read(gp, MII_BMCR, phy_addr);
-	val &= ~BMCR_ISOLATE;
-	val |= BMCR_RESET;
-	__phy_write(gp, MII_BMCR, val, phy_addr);
-
-	udelay(100);
-
-	while (limit--) {
-		val = __phy_read(gp, MII_BMCR, phy_addr);
-		if ((val & BMCR_RESET) == 0)
-			break;
-		udelay(10);
-	}
-	if ((val & BMCR_ISOLATE) && limit > 0)
-		__phy_write(gp, MII_BMCR, val & ~BMCR_ISOLATE, phy_addr);
-	
-	return (limit <= 0);
-}
-
-/* Must be invoked under gp->lock. */
-static void gem_init_bcm5201_phy(struct gem *gp)
-{
-	u16 data;
-
-	data = phy_read(gp, MII_BCM5201_MULTIPHY);
-	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
-	phy_write(gp, MII_BCM5201_MULTIPHY, data);
-}
-
-/* Must be invoked under gp->lock. */
-static void gem_init_bcm5400_phy(struct gem *gp)
-{
-	u16 data;
-
-	/* Configure for gigabit full duplex */
-	data = phy_read(gp, MII_BCM5400_AUXCONTROL);
-	data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
-	phy_write(gp, MII_BCM5400_AUXCONTROL, data);
-	
-	data = phy_read(gp, MII_BCM5400_GB_CONTROL);
-	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
-	phy_write(gp, MII_BCM5400_GB_CONTROL, data);
-	
-	mdelay(10);
-
-	/* Reset and configure cascaded 10/100 PHY */
-	gem_reset_one_mii_phy(gp, 0x1f);
-	
-	data = __phy_read(gp, MII_BCM5201_MULTIPHY, 0x1f);
-	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
-	__phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f);
-
-	data = phy_read(gp, MII_BCM5400_AUXCONTROL);
-	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
-	phy_write(gp, MII_BCM5400_AUXCONTROL, data);
-}
-
-/* Must be invoked under gp->lock. */
-static void gem_init_bcm5401_phy(struct gem *gp)
-{
-	u16 data;
-	int rev;
-
-	rev = phy_read(gp, MII_PHYSID2) & 0x000f;
-	if (rev == 0 || rev == 3) {
-		/* Some revisions of 5401 appear to need this
-		 * initialisation sequence to disable, according
-		 * to OF, "tap power management"
-		 * 
-		 * WARNING ! OF and Darwin don't agree on the
-		 * register addresses. OF seem to interpret the
-		 * register numbers below as decimal
-		 *
-		 * Note: This should (and does) match tg3_init_5401phy_dsp
-		 *       in the tg3.c driver. -DaveM
-		 */
-		phy_write(gp, 0x18, 0x0c20);
-		phy_write(gp, 0x17, 0x0012);
-		phy_write(gp, 0x15, 0x1804);
-		phy_write(gp, 0x17, 0x0013);
-		phy_write(gp, 0x15, 0x1204);
-		phy_write(gp, 0x17, 0x8006);
-		phy_write(gp, 0x15, 0x0132);
-		phy_write(gp, 0x17, 0x8006);
-		phy_write(gp, 0x15, 0x0232);
-		phy_write(gp, 0x17, 0x201f);
-		phy_write(gp, 0x15, 0x0a20);
-	}
-	
-	/* Configure for gigabit full duplex */
-	data = phy_read(gp, MII_BCM5400_GB_CONTROL);
-	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
-	phy_write(gp, MII_BCM5400_GB_CONTROL, data);
-
-	mdelay(1);
-
-	/* Reset and configure cascaded 10/100 PHY */
-	gem_reset_one_mii_phy(gp, 0x1f);
-	
-	data = __phy_read(gp, MII_BCM5201_MULTIPHY, 0x1f);
-	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
-	__phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f);
-}
-
-/* Must be invoked under gp->lock. */
-static void gem_init_bcm5411_phy(struct gem *gp)
-{
-	u16 data;
-
-	/* Here's some more Apple black magic to setup
-	 * some voltage stuffs.
-	 */
-	phy_write(gp, 0x1c, 0x8c23);
-	phy_write(gp, 0x1c, 0x8ca3);
-	phy_write(gp, 0x1c, 0x8c23);
-
-	/* Here, Apple seems to want to reset it, do
-	 * it as well
-	 */
-	phy_write(gp, MII_BMCR, BMCR_RESET);
-
-	/* Start autoneg */
-	phy_write(gp, MII_BMCR,
-		  (BMCR_ANENABLE | BMCR_FULLDPLX |
-		   BMCR_ANRESTART | BMCR_SPD2));
-
-	data = phy_read(gp, MII_BCM5400_GB_CONTROL);
-	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
-	phy_write(gp, MII_BCM5400_GB_CONTROL, data);
-}
-
-/* Must be invoked under gp->lock. */
 static void gem_init_phy(struct gem *gp)
 {
 	u32 mifcfg;
-
-	if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201)
-		phy_write(gp, MII_BCM5201_INTERRUPT, 0);
-
+	
 	/* Revert MIF CFG setting done on stop_phy */
 	mifcfg = readl(gp->regs + MIF_CFG);
 	mifcfg &= ~MIF_CFG_BBMODE;
@@ -1658,19 +1493,37 @@
 	
 #ifdef CONFIG_ALL_PPC
 	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
-		int i;
+		int i, j;
 
+		/* Those delay sucks, the HW seem to love them though, I'll
+		 * serisouly consider breaking some locks here to be able
+		 * to schedule instead
+		 */
 		pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
-		for (i = 0; i < 32; i++) {
-			gp->mii_phy_addr = i;
-			if (phy_read(gp, MII_BMCR) != 0xffff)
+		mdelay(10);
+		for (j = 0; j < 3; j++) {
+			/* Some PHYs used by apple have problem getting back to us,
+			 * we _know_ it's actually at addr 0, that's a hack, but
+			 * it helps to do that reset now. I suspect some motherboards
+			 * don't wire the PHY reset line properly, thus the PHY doesn't
+			 * come back with the above pmac_call_feature.
+			 */
+			gp->mii_phy_addr = 0;
+			phy_write(gp, MII_BMCR, BMCR_RESET);
+			/* We should probably break some locks here and schedule... */
+			mdelay(10);
+			for (i = 0; i < 32; i++) {
+				gp->mii_phy_addr = i;
+				if (phy_read(gp, MII_BMCR) != 0xffff)
+					break;
+			}
+			if (i == 32) {
+				printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
+				       gp->dev->name);
+				gp->mii_phy_addr = 0;
+			} else
 				break;
 		}
-		if (i == 32) {
-			printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
-			       gp->dev->name);
-			return;
-		}
 	}
 #endif /* CONFIG_ALL_PPC */
 
@@ -1693,79 +1546,12 @@
 
 	if (gp->phy_type == phy_mii_mdio0 ||
 	    gp->phy_type == phy_mii_mdio1) {
-		u32 phy_id;
-		u16 val;
-	
-		/* Take PHY out of isloate mode and reset it. */
-		gem_reset_one_mii_phy(gp, gp->mii_phy_addr);
-
-		phy_id = (phy_read(gp, MII_PHYSID1) << 16 | phy_read(gp, MII_PHYSID2))
-			 	& 0xfffffff0;
-		printk(KERN_INFO "%s: MII PHY ID: %x ", gp->dev->name, phy_id);
-		switch(phy_id) {
-		case 0x406210:
-			gp->phy_mod = phymod_bcm5201;
-			gem_init_bcm5201_phy(gp);
-			printk("BCM 5201\n");
-			break;
-
-		case 0x4061e0:
-			printk("BCM 5221\n");
-			gp->phy_mod = phymod_bcm5221;
-			break;
-
-		case 0x206040:
-			printk("BCM 5400\n");
-			gp->phy_mod = phymod_bcm5400;
-			gem_init_bcm5400_phy(gp);
-			gp->gigabit_capable = 1;
-			break;
-
-		case 0x206050:
-			printk("BCM 5401\n");
-			gp->phy_mod = phymod_bcm5401;
-			gem_init_bcm5401_phy(gp);
-			gp->gigabit_capable = 1;
-			break;
+	    	// XXX check for errors
+		mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
 
-		case 0x206070:
-			printk("BCM 5411\n");
-			gp->phy_mod = phymod_bcm5411;
-			gem_init_bcm5411_phy(gp);
-			gp->gigabit_capable = 1;
-			break;
-		case 0x1410c60:
-			printk("M1011 (Marvel ?)\n");
-			gp->phy_mod = phymod_m1011;
-			gp->gigabit_capable = 1;
-			break;
-
-		case 0x18074c0:
-			printk("Lucent\n");
-			gp->phy_mod = phymod_generic;
-			break;
-
-		case 0x437420:
-			printk("Enable Semiconductor\n");
-			gp->phy_mod = phymod_generic;
-			break;
-
-		default:
-			printk("Unknown (Using generic mode)\n");
-			gp->phy_mod = phymod_generic;
-			break;
-		};
-
-		/* Init advertisement and enable autonegotiation. */
-		val = phy_read(gp, MII_BMCR);
-		val &= ~BMCR_ANENABLE;
-		phy_write(gp, MII_BMCR, val);
-		udelay(10);
-		
-		phy_write(gp, MII_ADVERTISE,
-			  phy_read(gp, MII_ADVERTISE) |
-			  (ADVERTISE_10HALF | ADVERTISE_10FULL |
-			   ADVERTISE_100HALF | ADVERTISE_100FULL));
+		/* Init PHY */
+		if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
+			gp->phy_mii.def->ops->init(&gp->phy_mii);
 	} else {
 		u32 val;
 		int limit;
@@ -1822,13 +1608,7 @@
 		else
 			val |= PCS_SCTRL_LOOP;
 		writel(val, gp->regs + PCS_SCTRL);
-		gp->gigabit_capable = 1;
 	}
-
-	/* BMCR_SPD2 is a broadcom 54xx specific thing afaik */
-	if (gp->phy_mod != phymod_bcm5400 && gp->phy_mod != phymod_bcm5401 &&
-	    gp->phy_mod != phymod_bcm5411)
-	    	gp->link_cntl &= ~BMCR_SPD2;
 }
 
 /* Must be invoked under gp->lock. */
@@ -1917,9 +1697,7 @@
 {
 	unsigned char *e = &gp->dev->dev_addr[0];
 
-	if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
-	    gp->pdev->device == PCI_DEVICE_ID_SUN_GEM)
-		writel(0x1bf0, gp->regs + MAC_SNDPAUSE);
+	writel(0x1bf0, gp->regs + MAC_SNDPAUSE);
 
 	writel(0x00, gp->regs + MAC_IPG0);
 	writel(0x08, gp->regs + MAC_IPG1);
@@ -1956,7 +1734,9 @@
 	writel(0, gp->regs + MAC_AF0MSK);
 
 	gp->mac_rx_cfg = gem_setup_multicast(gp);
-
+#ifdef STRIP_FCS
+	gp->mac_rx_cfg |= MAC_RXCFG_SFCS;
+#endif
 	writel(0, gp->regs + MAC_NCOLL);
 	writel(0, gp->regs + MAC_FASUCC);
 	writel(0, gp->regs + MAC_ECOLL);
@@ -2132,12 +1912,15 @@
 		/* Default aneg parameters */
 		gp->timer_ticks = 0;
 		gp->lstate = link_down;
+		netif_carrier_off(gp->dev);
 
 		/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
 		gem_begin_auto_negotiation(gp, NULL);
 	} else {
-		if (gp->lstate == link_up)
+		if (gp->lstate == link_up) {
+			netif_carrier_on(gp->dev);
 			gem_set_link_modes(gp);
+		}
 	}
 }
 
@@ -2187,9 +1970,6 @@
 {
 	u32 mifcfg;
 
-	if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201)
-		phy_write(gp, MII_BCM5201_INTERRUPT, 0);
-
 	/* Make sure we aren't polling PHY status change. We
 	 * don't currently use that feature though
 	 */
@@ -2197,9 +1977,6 @@
 	mifcfg &= ~MIF_CFG_POLL;
 	writel(mifcfg, gp->regs + MIF_CFG);
 
-	/* Here's a strange hack used by both MacOS 9 and X */
-	phy_write(gp, MII_LPA, phy_read(gp, MII_LPA));
-
 	if (gp->wake_on_lan) {
 		/* Setup wake-on-lan */
 	} else
@@ -2213,21 +1990,12 @@
 		gem_stop(gp);
 		writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
 		writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
-		if (gp->phy_mod == phymod_bcm5400 || gp->phy_mod == phymod_bcm5401 ||
-		    gp->phy_mod == phymod_bcm5411) {
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
-			phy_write(gp, MII_BMCR, BMCR_PDOWN);
-#endif
-		} else if (gp->phy_mod == phymod_bcm5201 || gp->phy_mod == phymod_bcm5221) {
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
-			u16 val = phy_read(gp, MII_BCM5201_AUXMODE2)
-			phy_write(gp, MII_BCM5201_AUXMODE2,
-				  val & ~MII_BCM5201_AUXMODE2_LOWPOWER);
-#endif				
-			phy_write(gp, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
-		} else if (gp->phy_mod == phymod_m1011)
-			phy_write(gp, MII_BMCR, BMCR_PDOWN);
+	}
+
+	if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
+		gp->phy_mii.def->ops->suspend(&gp->phy_mii, 0 /* wake on lan options */);
 
+	if (!gp->wake_on_lan) {
 		/* According to Apple, we must set the MDIO pins to this begnign
 		 * state or we may 1) eat more current, 2) damage some PHYs
 		 */
@@ -2529,7 +2297,11 @@
 	netif_stop_queue(dev);
 
 	rxcfg = readl(gp->regs + MAC_RXCFG);
-	gp->mac_rx_cfg = rxcfg_new = gem_setup_multicast(gp);
+	rxcfg_new = gem_setup_multicast(gp);
+#ifdef STRIP_FCS
+	rxcfg_new |= MAC_RXCFG_SFCS;
+#endif
+	gp->mac_rx_cfg = rxcfg_new;
 	
 	writel(rxcfg & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
 	while (readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB) {
@@ -2554,8 +2326,6 @@
 static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user)
 {
 	struct gem *gp = dev->priv;
-	u16 bmcr;
-	int full_duplex, speed, pause;
 	struct ethtool_cmd ecmd;
 
 	if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
@@ -2578,41 +2348,36 @@
 	}
 
 	case ETHTOOL_GSET:
-		ecmd.supported =
+		if (gp->phy_type == phy_mii_mdio0 ||
+	     	    gp->phy_type == phy_mii_mdio1) {
+	     	    	if (gp->phy_mii.def)
+	     	    		ecmd.supported = gp->phy_mii.def->features;
+	     	    	else
+	     	    		ecmd.supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
+
+			/* XXX hardcoded stuff for now */
+			ecmd.port = PORT_MII;
+			ecmd.transceiver = XCVR_EXTERNAL;
+			ecmd.phy_address = 0; /* XXX fixed PHYAD */
+
+			/* Return current PHY settings */
+			spin_lock_irq(&gp->lock);
+			ecmd.autoneg = gp->want_autoneg;
+			ecmd.speed = gp->phy_mii.speed;
+			ecmd.duplex = gp->phy_mii.duplex;			
+			ecmd.advertising = gp->phy_mii.advertising;
+			/* If we started with a forced mode, we don't have a default
+			 * advertise set, we need to return something sensible so
+			 * userland can re-enable autoneg properly */
+			if (ecmd.advertising == 0)
+				ecmd.advertising = ecmd.supported;
+			spin_unlock_irq(&gp->lock);
+		} else { // XXX PCS ?
+	     	    ecmd.supported =
 			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
 			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-			 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
-
-		if (gp->gigabit_capable)
-			ecmd.supported |=
-				(SUPPORTED_1000baseT_Half |
-				 SUPPORTED_1000baseT_Full);
-
-		/* XXX hardcoded stuff for now */
-		ecmd.port = PORT_MII;
-		ecmd.transceiver = XCVR_EXTERNAL;
-		ecmd.phy_address = 0; /* XXX fixed PHYAD */
-
-		/* Record PHY settings if HW is on. */
-		spin_lock_irq(&gp->lock);
-		if (gp->hw_running) {
-			bmcr = phy_read(gp, MII_BMCR);
-			gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause);
-		} else
-			bmcr = 0;
-		spin_unlock_irq(&gp->lock);
-		if (bmcr & BMCR_ANENABLE) {
-			ecmd.autoneg = AUTONEG_ENABLE;
-			ecmd.speed = speed == 10 ? SPEED_10 : (speed == 1000 ? SPEED_1000 : SPEED_100);
-			ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-		} else {
-			ecmd.autoneg = AUTONEG_DISABLE;
-			ecmd.speed =
-				(bmcr & BMCR_SPEED100) ?
-				SPEED_100 : SPEED_10;
-			ecmd.duplex =
-				(bmcr & BMCR_FULLDPLX) ?
-				DUPLEX_FULL : DUPLEX_HALF;
+			 SUPPORTED_Autoneg);
+		    ecmd.advertising = ecmd.supported;
 		}
 		if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
 			return -EFAULT;
@@ -2627,13 +2392,18 @@
 		    ecmd.autoneg != AUTONEG_DISABLE)
 			return -EINVAL;
 
+		if (ecmd.autoneg == AUTONEG_ENABLE &&
+		    ecmd.advertising == 0)
+		    	return -EINVAL;
+
 		if (ecmd.autoneg == AUTONEG_DISABLE &&
-		    ((ecmd.speed != SPEED_100 &&
+		    ((ecmd.speed != SPEED_1000 &&
+		      ecmd.speed != SPEED_100 &&
 		      ecmd.speed != SPEED_10) ||
 		     (ecmd.duplex != DUPLEX_HALF &&
 		      ecmd.duplex != DUPLEX_FULL)))
 			return -EINVAL;
-
+	      
 		/* Apply settings and restart link process. */
 		spin_lock_irq(&gp->lock);
 		gem_begin_auto_negotiation(gp, &ecmd);
@@ -2642,7 +2412,7 @@
 		return 0;
 
 	case ETHTOOL_NWAY_RST:
-		if ((gp->link_cntl & BMCR_ANENABLE) == 0)
+		if (!gp->want_autoneg)
 			return -EINVAL;
 
 		/* Restart link process. */
@@ -2746,15 +2516,21 @@
 		/* Fallthrough... */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-		data->val_out = __phy_read(gp, data->reg_num & 0x1f, data->phy_id & 0x1f);
-		rc = 0;
+		if (!gp->hw_running)
+			rc = -EIO;
+		else {
+			data->val_out = __phy_read(gp, data->phy_id & 0x1f, data->reg_num & 0x1f);
+			rc = 0;
+		}
 		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN)) {
+		if (!capable(CAP_NET_ADMIN))
 			rc = -EPERM;
-		} else {
-			__phy_write(gp, data->reg_num & 0x1f, data->val_in, data->phy_id & 0x1f);
+		else if (!gp->hw_running)
+			rc = -EIO;
+		else {
+			__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 			rc = 0;
 		}
 		break;
@@ -2856,8 +2632,7 @@
 		printk(KERN_ERR "%s: can't get mac-address\n", dev->name);
 		return -1;
 	}
-#warning MAX_ADDR_LEN is now 32 bytes instead of 8, please fix this as appropriate
-	memcpy(dev->dev_addr, addr, MAX_ADDR_LEN);
+	memcpy(dev->dev_addr, addr, 6);
 #else
 	get_gem_mac_nonobp(gp->pdev, gp->dev->dev_addr);
 #endif
@@ -2928,6 +2703,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	gp = dev->priv;
 
@@ -2941,7 +2717,7 @@
 	dev->base_addr = (long) pdev;
 	gp->dev = dev;
 
-	gp->msg_enable = (gem_debug < 0 ? DEFAULT_MSG : gem_debug);
+	gp->msg_enable = DEFAULT_MSG;
 
 	spin_lock_init(&gp->lock);
 	init_MUTEX(&gp->pm_sem);
@@ -2957,13 +2733,9 @@
 	INIT_WORK(&gp->pm_task, gem_pm_task, gp);
 	INIT_WORK(&gp->reset_task, gem_reset_task, gp);
 	
-	/* Default link parameters */
-	if (link_mode >= 0 && link_mode <= 6)
-		gp->link_cntl = link_modes[link_mode];
-	else
-		gp->link_cntl = BMCR_ANENABLE;
 	gp->lstate = link_down;
 	gp->timer_ticks = 0;
+	netif_carrier_off(dev);
 
 	gp->regs = (unsigned long) ioremap(gemreg_base, gemreg_len);
 	if (gp->regs == 0UL) {
@@ -2984,15 +2756,17 @@
 	gem_stop(gp);
 	spin_unlock_irq(&gp->lock);
 
+	/* Fill up the mii_phy structure (even if we won't use it) */
+	gp->phy_mii.dev = dev;
+	gp->phy_mii.mdio_read = _phy_read;
+	gp->phy_mii.mdio_write = _phy_write;
+
+	/* By default, we start with autoneg */
+	gp->want_autoneg = 1;
+	
 	if (gem_check_invariants(gp))
 		goto err_out_iounmap;
 
-	spin_lock_irq(&gp->lock);
-	gp->hw_running = 1;
-	gem_init_phy(gp);
-	gem_begin_auto_negotiation(gp, NULL);
-	spin_unlock_irq(&gp->lock);
-
 	/* It is guaranteed that the returned buffer will be at least
 	 * PAGE_SIZE aligned.
 	 */
@@ -3019,12 +2793,23 @@
 
 	printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet ",
 	       dev->name);
-
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? ' ' : ':');
 	printk("\n");
 
+	/* Detect & init PHY, start autoneg */
+	spin_lock_irq(&gp->lock);
+	gp->hw_running = 1;
+	gem_init_phy(gp);
+	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock_irq(&gp->lock);
+
+	if (gp->phy_type == phy_mii_mdio0 ||
+     	    gp->phy_type == phy_mii_mdio1)
+		printk(KERN_INFO "%s: Found %s PHY\n", dev->name, 
+			gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+
 	pci_set_drvdata(pdev, dev);
 
 	dev->open = gem_open;
diff -urN linux-2.5.69-bk14/drivers/net/sungem.h linux-2.5.69-bk15/drivers/net/sungem.h
--- linux-2.5.69-bk14/drivers/net/sungem.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sungem.h	2003-05-21 04:47:33.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: sungem.h,v 1.12 2002/01/23 15:40:45 davem Exp $
+/* $Id: sungem.h,v 1.10.2.4 2002/03/11 08:54:48 davem Exp $
  * sungem.h: Definitions for Sun GEM ethernet driver.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -936,16 +936,6 @@
 	phy_serdes,
 };
 
-enum gem_phy_model {
-	phymod_generic,
-	phymod_bcm5201,
-	phymod_bcm5221,
-	phymod_bcm5400,
-	phymod_bcm5401,
-	phymod_bcm5411,
-	phymod_m1011,
-};
-
 enum link_state {
 	link_down = 0,	/* No link, will retry */
 	link_aneg,	/* Autoneg in progress */
@@ -980,26 +970,25 @@
 	struct net_device_stats net_stats;
 
 	enum gem_phy_type	phy_type;
-	enum gem_phy_model	phy_mod;
+	struct mii_phy		phy_mii;
+	
 	int			tx_fifo_sz;
 	int			rx_fifo_sz;
 	int			rx_pause_off;
 	int			rx_pause_on;
 	int			mii_phy_addr;
-	int			gigabit_capable;
 
 	u32			mac_rx_cfg;
 	u32			swrst_base;
 
 	/* Autoneg & PHY control */
-	int			link_cntl;
-	int			link_advertise;
-	int			link_fcntl;
+	int			want_autoneg;
+	int			last_forced_speed;
 	enum link_state		lstate;
 	struct timer_list	link_timer;
 	int			timer_ticks;
 	int			wake_on_lan;
-	struct work_struct			reset_task;
+	struct work_struct	reset_task;
 	volatile int		reset_task_pending;
 	
 	/* Diagnostic counters and state. */
@@ -1014,6 +1003,9 @@
 #endif
 };
 
+#define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) \
+				&& gp->phy_mii.def && gp->phy_mii.def->ops)
+			
 #define ALIGNED_RX_SKB_ADDR(addr) \
         ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
 static __inline__ struct sk_buff *gem_alloc_skb(int size, int gfp_flags)
diff -urN linux-2.5.69-bk14/drivers/net/sungem_phy.c linux-2.5.69-bk15/drivers/net/sungem_phy.c
--- linux-2.5.69-bk14/drivers/net/sungem_phy.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk15/drivers/net/sungem_phy.c	2003-05-21 04:47:33.000000000 -0700
@@ -0,0 +1,838 @@
+/*
+ * PHY drivers for the sungem ethernet driver.
+ * 
+ * This file could be shared with other drivers.
+ * 
+ * (c) 2002, Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ *
+ * TODO:
+ *  - Implement WOL
+ *  - Add support for PHYs that provide an IRQ line
+ *  - Eventually moved the entire polling state machine in
+ *    there (out of the eth driver), so that it can easily be
+ *    skipped on PHYs that implement it in hardware.
+ *  - On LXT971 & BCM5201, Apple uses some chip specific regs
+ *    to read the link status. Figure out why and if it makes
+ *    sense to do the same (magic aneg ?)
+ *  - Apple has some additional power management code for some
+ *    Broadcom PHYs that they "hide" from the OpenSource version
+ *    of darwin, still need to reverse engineer that
+ */
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+
+#include "sungem_phy.h"
+
+/* Link modes of the BCM5400 PHY */
+static int phy_BCM5400_link_table[8][3] = {
+	{ 0, 0, 0 },	/* No link */
+	{ 0, 0, 0 },	/* 10BT Half Duplex */
+	{ 1, 0, 0 },	/* 10BT Full Duplex */
+	{ 0, 1, 0 },	/* 100BT Half Duplex */
+	{ 0, 1, 0 },	/* 100BT Half Duplex */
+	{ 1, 1, 0 },	/* 100BT Full Duplex*/
+	{ 1, 0, 1 },	/* 1000BT */
+	{ 1, 0, 1 },	/* 1000BT */
+};
+
+static inline int __phy_read(struct mii_phy* phy, int id, int reg)
+{
+	return phy->mdio_read(phy->dev, id, reg);
+}
+
+static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
+{
+	phy->mdio_write(phy->dev, id, reg, val);
+}
+
+static inline int phy_read(struct mii_phy* phy, int reg)
+{
+	return phy->mdio_read(phy->dev, phy->mii_id, reg);
+}
+
+static inline void phy_write(struct mii_phy* phy, int reg, int val)
+{
+	phy->mdio_write(phy->dev, phy->mii_id, reg, val);
+}
+
+static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
+{
+	u16 val;
+	int limit = 10000;
+	
+	val = __phy_read(phy, phy_id, MII_BMCR);
+	val &= ~BMCR_ISOLATE;
+	val |= BMCR_RESET;
+	__phy_write(phy, phy_id, MII_BMCR, val);
+
+	udelay(100);
+
+	while (limit--) {
+		val = __phy_read(phy, phy_id, MII_BMCR);
+		if ((val & BMCR_RESET) == 0)
+			break;
+		udelay(10);
+	}
+	if ((val & BMCR_ISOLATE) && limit > 0)
+		__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
+	
+	return (limit <= 0);
+}
+
+static int bcm5201_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5201_MULTIPHY);
+	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
+	phy_write(phy, MII_BCM5201_MULTIPHY, data);
+
+	return 0;
+}
+
+static int bcm5201_suspend(struct mii_phy* phy, int wol_options)
+{
+	if (!wol_options)
+		phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+
+	/* Here's a strange hack used by both MacOS 9 and X */
+	phy_write(phy, MII_LPA, phy_read(phy, MII_LPA));
+	
+	if (!wol_options) {
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+		u16 val = phy_read(phy, MII_BCM5201_AUXMODE2)
+		phy_write(phy, MII_BCM5201_AUXMODE2,
+			  val & ~MII_BCM5201_AUXMODE2_LOWPOWER);
+#endif			
+		phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
+	}
+
+	return 0;
+}
+
+static int bcm5221_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
+		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+		data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	return 0;
+}
+
+static int bcm5400_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	/* Configure for gigabit full duplex */
+	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
+	data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
+	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
+	
+	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+	
+	mdelay(10);
+
+	/* Reset and configure cascaded 10/100 PHY */
+	(void)reset_one_mii_phy(phy, 0x1f);
+	
+	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
+	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
+	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
+	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
+
+	return 0;
+}
+
+static int bcm5400_suspend(struct mii_phy* phy, int wol_options)
+{
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+	phy_write(phy, MII_BMCR, BMCR_PDOWN);
+#endif
+	return 0;
+}
+
+static int bcm5401_init(struct mii_phy* phy)
+{
+	u16 data;
+	int rev;
+
+	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+	if (rev == 0 || rev == 3) {
+		/* Some revisions of 5401 appear to need this
+		 * initialisation sequence to disable, according
+		 * to OF, "tap power management"
+		 * 
+		 * WARNING ! OF and Darwin don't agree on the
+		 * register addresses. OF seem to interpret the
+		 * register numbers below as decimal
+		 *
+		 * Note: This should (and does) match tg3_init_5401phy_dsp
+		 *       in the tg3.c driver. -DaveM
+		 */
+		phy_write(phy, 0x18, 0x0c20);
+		phy_write(phy, 0x17, 0x0012);
+		phy_write(phy, 0x15, 0x1804);
+		phy_write(phy, 0x17, 0x0013);
+		phy_write(phy, 0x15, 0x1204);
+		phy_write(phy, 0x17, 0x8006);
+		phy_write(phy, 0x15, 0x0132);
+		phy_write(phy, 0x17, 0x8006);
+		phy_write(phy, 0x15, 0x0232);
+		phy_write(phy, 0x17, 0x201f);
+		phy_write(phy, 0x15, 0x0a20);
+	}
+	
+	/* Configure for gigabit full duplex */
+	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+	mdelay(10);
+
+	/* Reset and configure cascaded 10/100 PHY */
+	(void)reset_one_mii_phy(phy, 0x1f);
+	
+	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
+	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+	return 0;
+}
+
+static int bcm5401_suspend(struct mii_phy* phy, int wol_options)
+{
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+	phy_write(phy, MII_BMCR, BMCR_PDOWN);
+#endif
+	return 0;
+}
+
+static int bcm5411_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	/* Here's some more Apple black magic to setup
+	 * some voltage stuffs.
+	 */
+	phy_write(phy, 0x1c, 0x8c23);
+	phy_write(phy, 0x1c, 0x8ca3);
+	phy_write(phy, 0x1c, 0x8c23);
+
+	/* Here, Apple seems to want to reset it, do
+	 * it as well
+	 */
+	phy_write(phy, MII_BMCR, BMCR_RESET);
+	phy_write(phy, MII_BMCR, 0x1340);
+
+	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+	mdelay(10);
+
+	/* Reset and configure cascaded 10/100 PHY */
+	(void)reset_one_mii_phy(phy, 0x1f);
+	
+	return 0;
+}
+
+static int bcm5411_suspend(struct mii_phy* phy, int wol_options)
+{
+	phy_write(phy, MII_BMCR, BMCR_PDOWN);
+
+	return 0;
+}
+
+static int bcm5421_init(struct mii_phy* phy)
+{
+	u16 data;
+	int rev;
+
+	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+	if (rev == 0) {
+		/* This is borrowed from MacOS
+		 */
+		phy_write(phy, 0x18, 0x1007);
+		data = phy_read(phy, 0x18);
+		phy_write(phy, 0x18, data | 0x0400);
+		phy_write(phy, 0x18, 0x0007);
+		data = phy_read(phy, 0x18);
+		phy_write(phy, 0x18, data | 0x0800);
+		phy_write(phy, 0x17, 0x000a);
+		data = phy_read(phy, 0x15);
+		phy_write(phy, 0x15, data | 0x0200);
+	}
+#if 0
+	/* This has to be verified before I enable it */
+	/* Enable automatic low-power */
+	phy_write(phy, 0x1c, 0x9002);
+	phy_write(phy, 0x1c, 0xa821);
+	phy_write(phy, 0x1c, 0x941d);
+#endif
+	return 0;
+}
+
+static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	u16 ctl, adv;
+	
+	phy->autoneg = 1;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	/* Setup 1000BT advertise */
+	adv = phy_read(phy, MII_1000BASETCONTROL);
+	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
+	if (advertise & SUPPORTED_1000baseT_Half)
+		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+	if (advertise & SUPPORTED_1000baseT_Full)
+		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_1000BASETCONTROL, adv);
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	u16 ctl;
+	
+	phy->autoneg = 0;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
+
+	/* First reset the PHY */
+	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+	/* Select speed & duplex */
+	switch(speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	case SPEED_1000:
+		ctl |= BMCR_SPD2;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+
+	// XXX Should we set the sungem to GII now on 1000BT ?
+	
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int bcm54xx_read_link(struct mii_phy *phy)
+{
+	int link_mode;	
+	u16 val;
+	
+	if (phy->autoneg) {
+	    	val = phy_read(phy, MII_BCM5400_AUXSTATUS);
+		link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
+			     MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
+		phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
+		phy->speed = phy_BCM5400_link_table[link_mode][2] ?
+				SPEED_1000 :
+				(phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
+		val = phy_read(phy, MII_LPA);
+		phy->pause = ((val & LPA_PAUSE) != 0);
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	return 0;
+}
+
+static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	u16 ctl, adv;
+	
+	phy->autoneg = 1;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	/* Setup 1000BT advertise & enable crossover detect
+	 * XXX How do we advertise 1000BT ? Darwin source is
+	 * confusing here, they read from specific control and
+	 * write to control... Someone has specs for those
+	 * beasts ?
+	 */
+	adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
+	adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
+	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+			MII_1000BASETCONTROL_HALFDUPLEXCAP);
+	if (advertise & SUPPORTED_1000baseT_Half)
+		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+	if (advertise & SUPPORTED_1000baseT_Full)
+		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_1000BASETCONTROL, adv);
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	u16 ctl, ctl2;
+	
+	phy->autoneg = 0;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
+	ctl |= BMCR_RESET;
+
+	/* Select speed & duplex */
+	switch(speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	/* I'm not sure about the one below, again, Darwin source is
+	 * quite confusing and I lack chip specs
+	 */
+	case SPEED_1000:
+		ctl |= BMCR_SPD2;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+
+	/* Disable crossover. Again, the way Apple does it is strange,
+	 * though I don't assume they are wrong ;)
+	 */
+	ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
+	ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
+		MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
+		MII_1000BASETCONTROL_FULLDUPLEXCAP |
+		MII_1000BASETCONTROL_HALFDUPLEXCAP);
+	if (speed == SPEED_1000)
+		ctl2 |= (fd == DUPLEX_FULL) ?
+			MII_1000BASETCONTROL_FULLDUPLEXCAP :
+			MII_1000BASETCONTROL_HALFDUPLEXCAP;
+	phy_write(phy, MII_1000BASETCONTROL, ctl2);
+
+	// XXX Should we set the sungem to GII now on 1000BT ?
+	
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int marvell_read_link(struct mii_phy *phy)
+{
+	u16 status;
+
+	if (phy->autoneg) {
+		status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
+		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
+			return -EAGAIN;
+		if (status & MII_M1011_PHY_SPEC_STATUS_1000)
+			phy->speed = SPEED_1000;
+		else if (status & MII_M1011_PHY_SPEC_STATUS_100)
+			phy->speed = SPEED_100;
+		else
+			phy->speed = SPEED_10;
+		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+			phy->duplex = DUPLEX_FULL;
+		else
+			phy->duplex = DUPLEX_HALF;
+		phy->pause = 0; /* XXX Check against spec ! */
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	return 0;
+}
+
+static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	u16 ctl, adv;
+	
+	phy->autoneg = 1;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	u16 ctl;
+	
+	phy->autoneg = 0;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
+
+	/* First reset the PHY */
+	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+	/* Select speed & duplex */
+	switch(speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	case SPEED_1000:
+	default:
+		return -EINVAL;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int genmii_poll_link(struct mii_phy *phy)
+{
+	u16 status;
+	
+	(void)phy_read(phy, MII_BMSR);
+	status = phy_read(phy, MII_BMSR);
+	if ((status & BMSR_LSTATUS) == 0)
+		return 0;
+	if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
+		return 0;
+	return 1;
+}
+
+static int genmii_read_link(struct mii_phy *phy)
+{
+	u16 lpa;
+
+	if (phy->autoneg) {
+		lpa = phy_read(phy, MII_LPA);
+
+		if (lpa & (LPA_10FULL | LPA_100FULL))
+			phy->duplex = DUPLEX_FULL;
+		else
+			phy->duplex = DUPLEX_HALF;
+		if (lpa & (LPA_100FULL | LPA_100HALF))
+			phy->speed = SPEED_100;
+		else
+			phy->speed = SPEED_10;
+		phy->pause = 0;
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	 return 0;
+}
+
+
+#define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+				 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+				 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
+#define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
+				 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
+
+/* Broadcom BCM 5201 */
+static struct mii_phy_ops bcm5201_phy_ops = {
+	init:		bcm5201_init,
+	suspend:	bcm5201_suspend,
+	setup_aneg:	genmii_setup_aneg,
+	setup_forced:	genmii_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	genmii_read_link,
+};
+
+static struct mii_phy_def bcm5201_phy_def = {
+	phy_id:		0x00406210,
+	phy_id_mask:	0xfffffff0,
+	name:		"BCM5201",
+	features:	MII_BASIC_FEATURES,
+	magic_aneg:	0,
+	ops:		&bcm5201_phy_ops
+};
+
+/* Broadcom BCM 5221 */
+static struct mii_phy_ops bcm5221_phy_ops = {
+	suspend:	bcm5201_suspend,
+	init:		bcm5221_init,
+	setup_aneg:	genmii_setup_aneg,
+	setup_forced:	genmii_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	genmii_read_link,
+};
+
+static struct mii_phy_def bcm5221_phy_def = {
+	phy_id:		0x004061e0,
+	phy_id_mask:	0xfffffff0,
+	name:		"BCM5221",
+	features:	MII_BASIC_FEATURES,
+	magic_aneg:	0,
+	ops:		&bcm5221_phy_ops
+};
+
+/* Broadcom BCM 5400 */
+static struct mii_phy_ops bcm5400_phy_ops = {
+	init:		bcm5400_init,
+	suspend:	bcm5400_suspend,
+	setup_aneg:	bcm54xx_setup_aneg,
+	setup_forced:	bcm54xx_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5400_phy_def = {
+	phy_id:		0x00206040,
+	phy_id_mask:	0xfffffff0,
+	name:		"BCM5400",
+	features:	MII_GBIT_FEATURES,
+	magic_aneg:	1,
+	ops:		&bcm5400_phy_ops
+};
+
+/* Broadcom BCM 5401 */
+static struct mii_phy_ops bcm5401_phy_ops = {
+	init:		bcm5401_init,
+	suspend:	bcm5401_suspend,
+	setup_aneg:	bcm54xx_setup_aneg,
+	setup_forced:	bcm54xx_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5401_phy_def = {
+	phy_id:		0x00206050,
+	phy_id_mask:	0xfffffff0,
+	name:		"BCM5401",
+	features:	MII_GBIT_FEATURES,
+	magic_aneg:	1,
+	ops:		&bcm5401_phy_ops
+};
+
+/* Broadcom BCM 5411 */
+static struct mii_phy_ops bcm5411_phy_ops = {
+	init:		bcm5411_init,
+	suspend:	bcm5411_suspend,
+	setup_aneg:	bcm54xx_setup_aneg,
+	setup_forced:	bcm54xx_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5411_phy_def = {
+	phy_id:		0x00206070,
+	phy_id_mask:	0xfffffff0,
+	name:		"BCM5411",
+	features:	MII_GBIT_FEATURES,
+	magic_aneg:	1,
+	ops:		&bcm5411_phy_ops
+};
+
+/* Broadcom BCM 5421 */
+static struct mii_phy_ops bcm5421_phy_ops = {
+	init:		bcm5421_init,
+	suspend:	bcm5411_suspend,
+	setup_aneg:	bcm54xx_setup_aneg,
+	setup_forced:	bcm54xx_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5421_phy_def = {
+	phy_id:		0x002060e0,
+	phy_id_mask:	0xfffffff0,
+	name:		"BCM5421",
+	features:	MII_GBIT_FEATURES,
+	magic_aneg:	1,
+	ops:		&bcm5421_phy_ops
+};
+
+/* Marvell 88E1101 (Apple seem to deal with 2 different revs,
+ * I masked out the 8 last bits to get both, but some specs
+ * would be useful here) --BenH.
+ */
+static struct mii_phy_ops marvell_phy_ops = {
+	setup_aneg:	marvell_setup_aneg,
+	setup_forced:	marvell_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	marvell_read_link
+};
+
+static struct mii_phy_def marvell_phy_def = {
+	phy_id:		0x01410c00,
+	phy_id_mask:	0xffffff00,
+	name:		"Marvell 88E1101",
+	features:	MII_GBIT_FEATURES,
+	magic_aneg:	1,
+	ops:		&marvell_phy_ops
+};
+
+/* Generic implementation for most 10/100 PHYs */
+static struct mii_phy_ops generic_phy_ops = {
+	setup_aneg:	genmii_setup_aneg,
+	setup_forced:	genmii_setup_forced,
+	poll_link:	genmii_poll_link,
+	read_link:	genmii_read_link
+};
+
+static struct mii_phy_def genmii_phy_def = {
+	phy_id:		0x00000000,
+	phy_id_mask:	0x00000000,
+	name:		"Generic MII",
+	features:	MII_BASIC_FEATURES,
+	magic_aneg:	0,
+	ops:		&generic_phy_ops
+};
+
+static struct mii_phy_def* mii_phy_table[] = {
+	&bcm5201_phy_def,
+	&bcm5221_phy_def,
+	&bcm5400_phy_def,
+	&bcm5401_phy_def,
+	&bcm5411_phy_def,
+	&bcm5421_phy_def,
+	&marvell_phy_def,
+	&genmii_phy_def,
+	NULL
+};
+
+int mii_phy_probe(struct mii_phy *phy, int mii_id)
+{
+	int rc;
+	u32 id;
+	struct mii_phy_def* def;
+	int i;
+
+	/* We do not reset the mii_phy structure as the driver
+	 * may re-probe the PHY regulary
+	 */
+	phy->mii_id = mii_id;
+	
+	/* Take PHY out of isloate mode and reset it. */
+	rc = reset_one_mii_phy(phy, mii_id);
+	if (rc)
+		goto fail;
+
+	/* Read ID and find matching entry */	
+	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2))
+			 	& 0xfffffff0;
+	for (i=0; (def = mii_phy_table[i]) != NULL; i++)
+		if ((id & def->phy_id_mask) == def->phy_id)
+			break;
+	/* Should never be NULL (we have a generic entry), but... */
+	if (def == NULL)
+		goto fail;
+
+	phy->def = def;
+	
+	return 0;
+fail:
+	phy->speed = 0;
+	phy->duplex = 0;
+	phy->pause = 0;
+	phy->advertising = 0;
+	return -ENODEV;
+}
+
+EXPORT_SYMBOL(mii_phy_probe);
+MODULE_LICENSE("GPL");
+
diff -urN linux-2.5.69-bk14/drivers/net/sungem_phy.h linux-2.5.69-bk15/drivers/net/sungem_phy.h
--- linux-2.5.69-bk14/drivers/net/sungem_phy.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk15/drivers/net/sungem_phy.h	2003-05-21 04:47:33.000000000 -0700
@@ -0,0 +1,116 @@
+#ifndef __SUNGEM_PHY_H__
+#define __SUNGEM_PHY_H__
+
+struct mii_phy;
+
+/* Operations supported by any kind of PHY */
+struct mii_phy_ops
+{
+	int		(*init)(struct mii_phy *phy);
+	int		(*suspend)(struct mii_phy *phy, int wol_options);
+	int		(*setup_aneg)(struct mii_phy *phy, u32 advertise);
+	int		(*setup_forced)(struct mii_phy *phy, int speed, int fd);
+	int		(*poll_link)(struct mii_phy *phy);
+	int		(*read_link)(struct mii_phy *phy);
+};
+
+/* Structure used to statically define an mii/gii based PHY */
+struct mii_phy_def
+{
+	u32				phy_id;		/* Concatenated ID1 << 16 | ID2 */
+	u32				phy_id_mask;	/* Significant bits */
+	u32				features;	/* Ethtool SUPPORTED_* defines */
+	int				magic_aneg;	/* Autoneg does all speed test for us */
+	const char*			name;
+	const struct mii_phy_ops*	ops;
+};
+
+/* An instance of a PHY, partially borrowed from mii_if_info */
+struct mii_phy
+{
+	struct mii_phy_def*	def;
+	int			advertising;
+	int			mii_id;
+
+	/* 1: autoneg enabled, 0: disabled */
+	int			autoneg;
+
+	/* forced speed & duplex (no autoneg)
+	 * partner speed & duplex & pause (autoneg)
+	 */
+	int			speed;
+	int			duplex;
+	int			pause;
+
+	/* Provided by host chip */
+	struct net_device*	dev;
+	int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
+	void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
+};
+
+/* Pass in a struct mii_phy with dev, mdio_read and mdio_write
+ * filled, the remaining fields will be filled on return
+ */
+extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
+
+
+/* MII definitions missing from mii.h */
+
+#define BMCR_SPD2	0x0040		/* Gigabit enable (bcm54xx)	*/
+#define LPA_PAUSE	0x0400
+
+/* More PHY registers (model specific) */
+
+/* MII BCM5201 MULTIPHY interrupt register */
+#define MII_BCM5201_INTERRUPT			0x1A
+#define MII_BCM5201_INTERRUPT_INTENABLE		0x4000
+
+#define MII_BCM5201_AUXMODE2			0x1B
+#define MII_BCM5201_AUXMODE2_LOWPOWER		0x0008
+
+#define MII_BCM5201_MULTIPHY                    0x1E
+
+/* MII BCM5201 MULTIPHY register bits */
+#define MII_BCM5201_MULTIPHY_SERIALMODE         0x0002
+#define MII_BCM5201_MULTIPHY_SUPERISOLATE       0x0008
+
+/* MII BCM5221 Additional registers */
+#define MII_BCM5221_TEST			0x1f
+#define MII_BCM5221_TEST_ENABLE_SHADOWS		0x0080
+#define MII_BCM5221_SHDOW_AUX_STAT2		0x1b
+#define MII_BCM5221_SHDOW_AUX_STAT2_APD		0x0020
+#define MII_BCM5221_SHDOW_AUX_MODE4		0x1a
+#define MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR	0x0004
+
+/* MII BCM5400 1000-BASET Control register */
+#define MII_BCM5400_GB_CONTROL			0x09
+#define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP	0x0200
+
+/* MII BCM5400 AUXCONTROL register */
+#define MII_BCM5400_AUXCONTROL                  0x18
+#define MII_BCM5400_AUXCONTROL_PWR10BASET       0x0004
+
+/* MII BCM5400 AUXSTATUS register */
+#define MII_BCM5400_AUXSTATUS                   0x19
+#define MII_BCM5400_AUXSTATUS_LINKMODE_MASK     0x0700
+#define MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT    8  
+
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL			0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP	0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP	0x0100
+
+/* Marvell 88E1011 PHY control */
+#define MII_M1011_PHY_SPEC_CONTROL		0x10
+#define MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX	0x20
+#define MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX	0x40
+
+/* Marvell 88E1011 PHY status */
+#define MII_M1011_PHY_SPEC_STATUS		0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000		0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100		0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK	0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX	0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED	0x0800
+
+#endif /* __SUNGEM_PHY_H__ */
diff -urN linux-2.5.69-bk14/drivers/net/sunhme.c linux-2.5.69-bk15/drivers/net/sunhme.c
--- linux-2.5.69-bk14/drivers/net/sunhme.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/sunhme.c	2003-05-21 04:47:33.000000000 -0700
@@ -3025,6 +3025,7 @@
 	if (!dev)
 		goto err_out;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (hme_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
diff -urN linux-2.5.69-bk14/drivers/net/tg3.c linux-2.5.69-bk15/drivers/net/tg3.c
--- linux-2.5.69-bk14/drivers/net/tg3.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tg3.c	2003-05-21 04:47:33.000000000 -0700
@@ -6764,6 +6764,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
diff -urN linux-2.5.69-bk14/drivers/net/tlan.c linux-2.5.69-bk15/drivers/net/tlan.c
--- linux-2.5.69-bk14/drivers/net/tlan.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tlan.c	2003-05-21 04:47:33.000000000 -0700
@@ -521,6 +521,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	
 	priv = dev->priv;
 
diff -urN linux-2.5.69-bk14/drivers/net/tulip/de2104x.c linux-2.5.69-bk15/drivers/net/tulip/de2104x.c
--- linux-2.5.69-bk14/drivers/net/tulip/de2104x.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/de2104x.c	2003-05-21 04:47:33.000000000 -0700
@@ -2006,6 +2006,7 @@
 		return -ENOMEM;
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	dev->open = de_open;
 	dev->stop = de_close;
 	dev->set_multicast_list = de_set_rx_mode;
diff -urN linux-2.5.69-bk14/drivers/net/tulip/de4x5.c linux-2.5.69-bk15/drivers/net/tulip/de4x5.c
--- linux-2.5.69-bk14/drivers/net/tulip/de4x5.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/de4x5.c	2003-05-21 04:47:33.000000000 -0700
@@ -1350,6 +1350,7 @@
     
     /* The DE4X5-specific entries in the device structure. */
     SET_MODULE_OWNER(dev);
+    SET_NETDEV_DEV(dev, &pdev->dev);
     dev->open = &de4x5_open;
     dev->hard_start_xmit = &de4x5_queue_pkt;
     dev->stop = &de4x5_close;
diff -urN linux-2.5.69-bk14/drivers/net/tulip/dmfe.c linux-2.5.69-bk15/drivers/net/tulip/dmfe.c
--- linux-2.5.69-bk14/drivers/net/tulip/dmfe.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/dmfe.c	2003-05-21 04:47:33.000000000 -0700
@@ -348,6 +348,7 @@
 	if (dev == NULL)
 		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_set_dma_mask(pdev, 0xffffffff)) {
 		printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
diff -urN linux-2.5.69-bk14/drivers/net/tulip/tulip_core.c linux-2.5.69-bk15/drivers/net/tulip/tulip_core.c
--- linux-2.5.69-bk14/drivers/net/tulip/tulip_core.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/tulip_core.c	2003-05-21 04:47:33.000000000 -0700
@@ -1360,6 +1360,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
 		printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) too small, "
 			"aborting\n", pdev->slot_name,
diff -urN linux-2.5.69-bk14/drivers/net/tulip/winbond-840.c linux-2.5.69-bk15/drivers/net/tulip/winbond-840.c
--- linux-2.5.69-bk14/drivers/net/tulip/winbond-840.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/winbond-840.c	2003-05-21 04:47:33.000000000 -0700
@@ -423,6 +423,7 @@
 	if (!dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_netdev;
diff -urN linux-2.5.69-bk14/drivers/net/tulip/xircom_cb.c linux-2.5.69-bk15/drivers/net/tulip/xircom_cb.c
--- linux-2.5.69-bk14/drivers/net/tulip/xircom_cb.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/xircom_cb.c	2003-05-21 04:47:33.000000000 -0700
@@ -276,6 +276,7 @@
 		return -ENODEV;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
 
 	private->dev = dev;
diff -urN linux-2.5.69-bk14/drivers/net/tulip/xircom_tulip_cb.c linux-2.5.69-bk15/drivers/net/tulip/xircom_tulip_cb.c
--- linux-2.5.69-bk14/drivers/net/tulip/xircom_tulip_cb.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tulip/xircom_tulip_cb.c	2003-05-21 04:47:33.000000000 -0700
@@ -560,6 +560,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	dev->base_addr = ioaddr;
 	dev->irq = pdev->irq;
diff -urN linux-2.5.69-bk14/drivers/net/tun.c linux-2.5.69-bk15/drivers/net/tun.c
--- linux-2.5.69-bk14/drivers/net/tun.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/tun.c	2003-05-21 04:47:33.000000000 -0700
@@ -379,7 +379,7 @@
 		tun->owner = -1;
 		tun->dev.init = tun_net_init;
 		tun->dev.priv = tun;
-		tun->dev.owner = THIS_MODULE;
+		SET_MODULE_OWNER(&tun->dev);
 
 		err = -EINVAL;
 
diff -urN linux-2.5.69-bk14/drivers/net/typhoon.c linux-2.5.69-bk15/drivers/net/typhoon.c
--- linux-2.5.69-bk14/drivers/net/typhoon.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/typhoon.c	2003-05-21 04:47:33.000000000 -0700
@@ -2266,6 +2266,7 @@
 		goto error_out;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	err = pci_enable_device(pdev);
 	if(err < 0) {
diff -urN linux-2.5.69-bk14/drivers/net/via-rhine.c linux-2.5.69-bk15/drivers/net/via-rhine.c
--- linux-2.5.69-bk14/drivers/net/via-rhine.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/via-rhine.c	2003-05-21 04:47:33.000000000 -0700
@@ -660,6 +660,7 @@
 		goto err_out;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	
 	if (pci_request_regions(pdev, shortname))
 		goto err_out_free_netdev;
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx-hw-comx.c linux-2.5.69-bk15/drivers/net/wan/comx-hw-comx.c
--- linux-2.5.69-bk14/drivers/net/wan/comx-hw-comx.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx-hw-comx.c	2003-05-21 04:47:33.000000000 -0700
@@ -1427,24 +1427,20 @@
 	NULL
 };
 
-#ifdef MODULE
-#define comx_hw_comx_init init_module
-#endif
-
-int __init comx_hw_comx_init(void)
+static int __init comx_hw_comx_init(void)
 {
 	comx_register_hardware(&comx_hw);
 	comx_register_hardware(&cmx_hw);
 	comx_register_hardware(&hicomx_hw);
-	memset(memory_used, 0, sizeof(memory_used));
 	return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit comx_hw_comx_exit(void)
 {
 	comx_unregister_hardware("comx");
 	comx_unregister_hardware("cmx");
 	comx_unregister_hardware("hicomx");
 }
-#endif
+
+module_init(comx_hw_comx_init);
+module_exit(comx_hw_comx_exit);
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx-hw-locomx.c linux-2.5.69-bk15/drivers/net/wan/comx-hw-locomx.c
--- linux-2.5.69-bk14/drivers/net/wan/comx-hw-locomx.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx-hw-locomx.c	2003-05-21 04:47:33.000000000 -0700
@@ -479,20 +479,16 @@
 	NULL
 };
 	
-#ifdef MODULE
-#define comx_hw_locomx_init init_module
-#endif
-
-int __init comx_hw_locomx_init(void)
+static int __init comx_hw_locomx_init(void)
 {
 	comx_register_hardware(&locomx_hw);
 	return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit comx_hw_locomx_exit(void)
 {
 	comx_unregister_hardware("locomx");
-	return;
 }
-#endif
+
+module_init(comx_hw_locomx_init);
+module_exit(comx_hw_locomx_exit);
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx-hw-mixcom.c linux-2.5.69-bk15/drivers/net/wan/comx-hw-mixcom.c
--- linux-2.5.69-bk14/drivers/net/wan/comx-hw-mixcom.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx-hw-mixcom.c	2003-05-21 04:47:33.000000000 -0700
@@ -944,21 +944,15 @@
 	NULL
 };
 	
-/* Module management */
-
-#ifdef MODULE
-#define comx_hw_mixcom_init init_module
-#endif
-
-int __init comx_hw_mixcom_init(void)
+static int __init comx_hw_mixcom_init(void)
 {
-	return(comx_register_hardware(&mixcomhw));
+	return comx_register_hardware(&mixcomhw);
 }
 
-#ifdef MODULE
-void
-cleanup_module(void)
+static void __exit comx_hw_mixcom_exit(void)
 {
 	comx_unregister_hardware("mixcom");
 }
-#endif
+
+module_init(comx_hw_mixcom_init);
+module_exit(comx_hw_mixcom_exit);
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx-proto-fr.c linux-2.5.69-bk15/drivers/net/wan/comx-proto-fr.c
--- linux-2.5.69-bk14/drivers/net/wan/comx-proto-fr.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx-proto-fr.c	2003-05-21 04:47:33.000000000 -0700
@@ -988,11 +988,7 @@
 	.hw_dump	= dlci_dump, 
 };
 
-#ifdef MODULE
-#define comx_proto_fr_init init_module
-#endif
-
-int __init comx_proto_fr_init(void)
+static int __init comx_proto_fr_init(void)
 {
 	int ret; 
 
@@ -1005,12 +1001,12 @@
 	return comx_register_protocol(&fr_slave_protocol);
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit comx_proto_fr_exit(void)
 {
 	comx_unregister_hardware(fr_dlci.name);
 	comx_unregister_protocol(fr_master_protocol.name);
 	comx_unregister_protocol(fr_slave_protocol.name);
 }
-#endif /* MODULE */
 
+module_init(comx_proto_fr_init);
+module_exit(comx_proto_fr_exit);
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx-proto-lapb.c linux-2.5.69-bk15/drivers/net/wan/comx-proto-lapb.c
--- linux-2.5.69-bk14/drivers/net/wan/comx-proto-lapb.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx-proto-lapb.c	2003-05-21 04:47:33.000000000 -0700
@@ -523,7 +523,7 @@
 	NULL 
 };
 
-int __init comx_proto_lapb_init(void)
+static int __init comx_proto_lapb_init(void)
 {
 	int ret;
 
@@ -539,9 +539,7 @@
 	comx_unregister_protocol(comx25_protocol.name);
 }
 
-#ifdef MODULE
 module_init(comx_proto_lapb_init);
-#endif
 module_exit(comx_proto_lapb_exit);
 
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx-proto-ppp.c linux-2.5.69-bk15/drivers/net/wan/comx-proto-ppp.c
--- linux-2.5.69-bk14/drivers/net/wan/comx-proto-ppp.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx-proto-ppp.c	2003-05-21 04:47:33.000000000 -0700
@@ -247,26 +247,24 @@
 	NULL 
 };
 
-
-#ifdef MODULE
-#define comx_proto_ppp_init init_module
-#endif
-
-int __init comx_proto_ppp_init(void)
+static int __init comx_proto_ppp_init(void)
 {
 	int ret;
 
-	if(0!=(ret=comx_register_protocol(&hdlc_protocol))) {
-		return ret;
+	ret = comx_register_protocol(&hdlc_protocol);
+	if (!ret) {
+		ret = comx_register_protocol(&syncppp_protocol);
+		if (ret)
+			comx_unregister_protocol(hdlc_protocol.name);
 	}
-	return comx_register_protocol(&syncppp_protocol);
+	return ret;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit comx_proto_ppp_exit(void)
 {
 	comx_unregister_protocol(syncppp_protocol.name);
 	comx_unregister_protocol(hdlc_protocol.name);
 }
-#endif /* MODULE */
 
+module_init(comx_proto_ppp_init);
+module_exit(comx_proto_ppp_exit);
diff -urN linux-2.5.69-bk14/drivers/net/wan/comx.c linux-2.5.69-bk15/drivers/net/wan/comx.c
--- linux-2.5.69-bk14/drivers/net/wan/comx.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/comx.c	2003-05-21 04:47:33.000000000 -0700
@@ -81,15 +81,6 @@
 MODULE_DESCRIPTION("Common code for the COMX synchronous serial adapters");
 MODULE_LICENSE("GPL");
 
-extern int comx_hw_comx_init(void);
-extern int comx_hw_locomx_init(void);
-extern int comx_hw_mixcom_init(void);
-extern int comx_proto_hdlc_init(void);
-extern int comx_proto_ppp_init(void);
-extern int comx_proto_syncppp_init(void);
-extern int comx_proto_lapb_init(void);
-extern int comx_proto_fr_init(void);
-
 static struct comx_hardware *comx_channels = NULL;
 static struct comx_protocol *comx_lines = NULL;
 
@@ -1078,11 +1069,7 @@
 	return -1;
 }
 
-#ifdef MODULE
-#define comx_init init_module
-#endif
-
-int __init comx_init(void)
+static int __init comx_init(void)
 {
 	struct proc_dir_entry *new_file;
 
@@ -1115,42 +1102,18 @@
 
 	printk(KERN_INFO "COMX: driver version %s (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>\n", 
 		VERSION);
-
-#ifndef MODULE
-#ifdef CONFIG_COMX_HW_COMX
-	comx_hw_comx_init();
-#endif
-#ifdef CONFIG_COMX_HW_LOCOMX
-	comx_hw_locomx_init();
-#endif
-#ifdef CONFIG_COMX_HW_MIXCOM
-	comx_hw_mixcom_init();
-#endif
-#ifdef CONFIG_COMX_PROTO_HDLC
-	comx_proto_hdlc_init();
-#endif
-#ifdef CONFIG_COMX_PROTO_PPP
-	comx_proto_ppp_init();
-#endif
-#ifdef CONFIG_COMX_PROTO_LAPB
-	comx_proto_lapb_init();
-#endif
-#ifdef CONFIG_COMX_PROTO_FR
-	comx_proto_fr_init();
-#endif
-#endif
-
 	return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit comx_exit(void)
 {
 	remove_proc_entry(FILENAME_HARDWARELIST, comx_root_dir);
 	remove_proc_entry(FILENAME_PROTOCOLLIST, comx_root_dir);
 	remove_proc_entry(comx_root_dir->name, &proc_root);
 }
-#endif
+
+module_init(comx_init);
+module_exit(comx_exit);
 
 EXPORT_SYMBOL(comx_register_hardware);
 EXPORT_SYMBOL(comx_unregister_hardware);
diff -urN linux-2.5.69-bk14/drivers/net/wan/cycx_main.c linux-2.5.69-bk15/drivers/net/wan/cycx_main.c
--- linux-2.5.69-bk14/drivers/net/wan/cycx_main.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/cycx_main.c	2003-05-21 04:47:33.000000000 -0700
@@ -13,6 +13,10 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* Please look at the bitkeeper changelog (or any other scm tool that ends up
+* importing bitkeeper changelog or that replaces bitkeeper in the future as
+* main tool for linux development).
+* 
 * 2001/05/09	acme		Fix MODULE_DESC for debug, .bss nitpicks,
 * 				some cleanups
 * 2000/07/13	acme		remove useless #ifdef MODULE and crap
@@ -46,11 +50,8 @@
 #include <linux/ioport.h>	/* request_region(), release_region() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/cyclomx.h>	/* cyclomx common user API definitions */
-#include <asm/uaccess.h>	/* kernel <-> user copy */
 #include <linux/init.h>         /* __init (when not using as a module) */
 
-/* Debug */
-
 unsigned int cycx_debug;
 
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
@@ -61,18 +62,17 @@
 
 /* Defines & Macros */
 
-#define	DRV_VERSION	0		/* version number */
-#define	DRV_RELEASE	10		/* release (minor version) number */
-#define	MAX_CARDS	1		/* max number of adapters */
+#define	CYCX_DRV_VERSION	0	/* version number */
+#define	CYCX_DRV_RELEASE	11	/* release (minor version) number */
+#define	CYCX_MAX_CARDS		1	/* max number of adapters */
 
-#define	CONFIG_CYCLOMX_CARDS 1
+#define	CONFIG_CYCX_CARDS 1
 
 /* Function Prototypes */
 
 /* WAN link driver entry points */
-static int setup(struct wan_device *wandev, wandev_conf_t *conf);
-static int shutdown(struct wan_device *wandev);
-static int ioctl(struct wan_device *wandev, unsigned cmd, unsigned long arg);
+static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf);
+static int cycx_wan_shutdown(struct wan_device *wandev);
 
 /* Miscellaneous functions */
 static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs);
@@ -82,12 +82,12 @@
  */
 
 /* private data */
-static char drvname[]	= "cyclomx";
-static char fullname[]	= "CYCLOM 2X(tm) Sync Card Driver";
-static char copyright[] = "(c) 1998-2001 Arnaldo Carvalho de Melo "
+static char cycx_drvname[] = "cyclomx";
+static char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
+static char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
 			  "<acme@conectiva.com.br>";
-static int ncards = CONFIG_CYCLOMX_CARDS;
-static struct cycx_device *card_array;	/* adapter data space */
+static int cycx_ncards = CONFIG_CYCX_CARDS;
+static struct cycx_device *cycx_card_array;	/* adapter data space */
 
 /* Kernel Loadable Module Entry Points */
 
@@ -103,51 +103,52 @@
  *		< 0	error.
  * Context:	process
  */
-int __init cyclomx_init(void)
+int __init cycx_init(void)
 {
 	int cnt, err = -ENOMEM;
 
 	printk(KERN_INFO "%s v%u.%u %s\n",
-		fullname, DRV_VERSION, DRV_RELEASE, copyright);
+		cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE,
+		cycx_copyright);
 
 	/* Verify number of cards and allocate adapter data space */
-	ncards = min_t(int, ncards, MAX_CARDS);
-	ncards = max_t(int, ncards, 1);
-	card_array = kmalloc(sizeof(struct cycx_device) * ncards, GFP_KERNEL);
-	if (!card_array)
+	cycx_ncards = min_t(int, cycx_ncards, CYCX_MAX_CARDS);
+	cycx_ncards = max_t(int, cycx_ncards, 1);
+	cycx_card_array = kmalloc(sizeof(struct cycx_device) * cycx_ncards,
+				  GFP_KERNEL);
+	if (!cycx_card_array)
 		goto out;
 
-	memset(card_array, 0, sizeof(struct cycx_device) * ncards);
+	memset(cycx_card_array, 0, sizeof(struct cycx_device) * cycx_ncards);
 
 	/* Register adapters with WAN router */
-	for (cnt = 0; cnt < ncards; ++cnt) {
-		struct cycx_device *card = &card_array[cnt];
+	for (cnt = 0; cnt < cycx_ncards; ++cnt) {
+		struct cycx_device *card = &cycx_card_array[cnt];
 		struct wan_device *wandev = &card->wandev;
 
-		sprintf(card->devname, "%s%d", drvname, cnt + 1);
+		sprintf(card->devname, "%s%d", cycx_drvname, cnt + 1);
 		wandev->magic    = ROUTER_MAGIC;
 		wandev->name     = card->devname;
 		wandev->private  = card;
-		wandev->setup    = setup;
-		wandev->shutdown = shutdown;
-		wandev->ioctl    = ioctl;
+		wandev->setup    = cycx_wan_setup;
+		wandev->shutdown = cycx_wan_shutdown;
 		err = register_wan_device(wandev);
 
 		if (err) {
 			printk(KERN_ERR "%s: %s registration failed with "
 					"error %d!\n",
-					drvname, card->devname, err);
+					cycx_drvname, card->devname, err);
 			break;
 		}
 	}
 
 	err = -ENODEV;
 	if (!cnt) {
-		kfree(card_array);
+		kfree(cycx_card_array);
 		goto out;
 	}
 	err = 0;
-	ncards = cnt;	/* adjust actual number of cards */
+	cycx_ncards = cnt;	/* adjust actual number of cards */
 out:	return err;
 }
 
@@ -156,16 +157,16 @@
  * o unregister all adapters from the WAN router
  * o release all remaining system resources
  */
-static void __exit cyclomx_cleanup(void)
+static void __exit cycx_exit(void)
 {
 	int i = 0;
 
-	for (; i < ncards; ++i) {
-		struct cycx_device *card = &card_array[i];
+	for (; i < cycx_ncards; ++i) {
+		struct cycx_device *card = &cycx_card_array[i];
 		unregister_wan_device(card->devname);
 	}
 
-	kfree(card_array);
+	kfree(cycx_card_array);
 }
 
 /* WAN Device Driver Entry Points */
@@ -181,9 +182,9 @@
  * configuration structure is in kernel memory (including extended data, if
  * any).
  */
-static int setup(struct wan_device *wandev, wandev_conf_t *conf)
+static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
 {
-	int err = -EFAULT;
+	int rc = -EFAULT;
 	struct cycx_device *card;
 	int irq;
 
@@ -193,11 +194,11 @@
 		goto out;
 
 	card = wandev->private;
-	err = -EBUSY;
+	rc = -EBUSY;
 	if (wandev->state != WAN_UNCONFIGURED)
 		goto out;
 
-	err = -EINVAL;
+	rc = -EINVAL;
 	if (!conf->data_size || !conf->data) {
 		printk(KERN_ERR "%s: firmware not found in configuration "
 				"data!\n", wandev->name);
@@ -228,8 +229,8 @@
 	card->lock	 = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&card->wait_stats);
 
-	err = cycx_setup(&card->hw, conf->data, conf->data_size);
-	if (err)
+	rc = cycx_setup(&card->hw, conf->data, conf->data_size);
+	if (rc)
 		goto out_irq;
 
 	/* Initialize WAN device data space */
@@ -244,22 +245,23 @@
 	switch (card->hw.fwid) {
 #ifdef CONFIG_CYCLOMX_X25
 	case CFID_X25_2X:
-		err = cyx_init(card, conf);
+		rc = cycx_x25_wan_init(card, conf);
 		break;
 #endif
 	default:
 		printk(KERN_ERR "%s: this firmware is not supported!\n",
 				wandev->name);
-		err = -EINVAL;
+		rc = -EINVAL;
 	}
 
-	if (err) {
+	if (rc) {
 		cycx_down(&card->hw);
 		goto out_irq;
 	}
 
-	err = 0;
-out:	return err;
+	rc = 0;
+out:
+	return rc;
 out_irq:
 	free_irq(irq, card);
 	goto out;
@@ -273,7 +275,7 @@
  * This function is called by the router when device is being unregistered or
  * when it handles ROUTER_DOWN IOCTL.
  */
-static int shutdown(struct wan_device *wandev)
+static int cycx_wan_shutdown(struct wan_device *wandev)
 {
 	int ret = -EFAULT;
 	struct cycx_device *card;
@@ -295,21 +297,6 @@
 out:	return ret;
 }
 
-/*
- * Driver I/O control.
- * o verify arguments
- * o perform requested action
- *
- * This function is called when router handles one of the reserved user
- * IOCTLs.  Note that 'arg' still points to user address space.
- *
- * no reserved ioctls for the cyclom 2x up to now
- */
-static int ioctl(struct wan_device *wandev, unsigned cmd, unsigned long arg)
-{
-	return -EINVAL;
-}
-
 /* Miscellaneous */
 /*
  * Cyclom 2X Interrupt Service Routine.
@@ -332,11 +319,12 @@
 	if (card->isr)
 		card->isr(card);
 	return IRQ_HANDLED;
-out:	return IRQ_NONE;
+out:
+	return IRQ_NONE;
 }
 
 /* Set WAN device state.  */
-void cyclomx_set_state(struct cycx_device *card, int state)
+void cycx_set_state(struct cycx_device *card, int state)
 {
 	unsigned long flags;
 	char *string_state = NULL;
@@ -360,5 +348,5 @@
 	spin_unlock_irqrestore(&card->lock, flags);
 }
 
-module_init(cyclomx_init);
-module_exit(cyclomx_cleanup);
+module_init(cycx_init);
+module_exit(cycx_exit);
diff -urN linux-2.5.69-bk14/drivers/net/wan/cycx_x25.c linux-2.5.69-bk15/drivers/net/wan/cycx_x25.c
--- linux-2.5.69-bk14/drivers/net/wan/cycx_x25.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/cycx_x25.c	2003-05-21 04:47:33.000000000 -0700
@@ -94,8 +94,8 @@
 #include <linux/cycx_x25.h>	/* X.25 firmware API definitions */
 
 /* Defines & Macros */
-#define MAX_CMD_RETRY	5
-#define X25_CHAN_MTU	2048	/* unfragmented logical channel MTU */
+#define CYCX_X25_MAX_CMD_RETRY 5
+#define CYCX_X25_CHAN_MTU 2048	/* unfragmented logical channel MTU */
 
 /* Data Structures */
 /* This is an extension of the 'struct net_device' we create for each network
@@ -123,56 +123,65 @@
 
 /* Function Prototypes */
 /* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev),
-	   new_if(struct wan_device *wandev, struct net_device *dev,
-		  wanif_conf_t *conf),
-	   del_if(struct wan_device *wandev, struct net_device *dev);
+static int cycx_wan_update(struct wan_device *wandev),
+	   cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
+			   wanif_conf_t *conf),
+	   cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev);
 
 /* Network device interface */
-static int if_init(struct net_device *dev),
-	   if_open(struct net_device *dev),
-	   if_close(struct net_device *dev),
-	   if_header(struct sk_buff *skb, struct net_device *dev,
-		     u16 type, void *daddr, void *saddr, unsigned len),
-	   if_rebuild_hdr(struct sk_buff *skb),
-	   if_send(struct sk_buff *skb, struct net_device *dev);
+static int cycx_netdevice_init(struct net_device *dev),
+	   cycx_netdevice_open(struct net_device *dev),
+	   cycx_netdevice_stop(struct net_device *dev),
+	   cycx_netdevice_hard_header(struct sk_buff *skb,
+				     struct net_device *dev, u16 type,
+				     void *daddr, void *saddr, unsigned len),
+	   cycx_netdevice_rebuild_header(struct sk_buff *skb),
+	   cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
+					  struct net_device *dev);
 
-static struct net_device_stats *if_stats(struct net_device *dev);
+static struct net_device_stats *
+			cycx_netdevice_get_stats(struct net_device *dev);
 
 /* Interrupt handlers */
-static void cyx_isr(struct cycx_device *card),
-	    tx_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd),
-	    rx_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd),
-	    log_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd),
-	    stat_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd),
-	    connect_confirm_intr(struct cycx_device *card,
+static void cycx_x25_irq_handler(struct cycx_device *card),
+	    cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd),
+	    cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd),
+	    cycx_x25_irq_log(struct cycx_device *card,
+			     struct cycx_x25_cmd *cmd),
+	    cycx_x25_irq_stat(struct cycx_device *card,
+			      struct cycx_x25_cmd *cmd),
+	    cycx_x25_irq_connect_confirm(struct cycx_device *card,
+					 struct cycx_x25_cmd *cmd),
+	    cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
+					    struct cycx_x25_cmd *cmd),
+	    cycx_x25_irq_connect(struct cycx_device *card,
 				 struct cycx_x25_cmd *cmd),
-	    disconnect_confirm_intr(struct cycx_device *card,
+	    cycx_x25_irq_disconnect(struct cycx_device *card,
 				    struct cycx_x25_cmd *cmd),
-	    connect_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd),
-	    disconnect_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd),
-	    spur_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd);
+	    cycx_x25_irq_spurious(struct cycx_device *card,
+				  struct cycx_x25_cmd *cmd);
 
 /* X.25 firmware interface functions */
-static int x25_configure(struct cycx_device *card,
-			 struct cycx_x25_config *conf),
-	   x25_get_stats(struct cycx_device *card),
-	   x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm, int len,
-		    void *buf),
-	   x25_connect_response(struct cycx_device *card,
+static int cycx_x25_configure(struct cycx_device *card,
+			      struct cycx_x25_config *conf),
+	   cycx_x25_get_stats(struct cycx_device *card),
+	   cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
+			 int len, void *buf),
+	   cycx_x25_connect_response(struct cycx_device *card,
 				struct cycx_x25_channel *chan),
-	   x25_disconnect_response(struct cycx_device *card, u8 link, u8 lcn);
+	   cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
+			   		u8 lcn);
 
 /* channel functions */
-static int chan_connect(struct net_device *dev),
-	   chan_send(struct net_device *dev, struct sk_buff *skb);
+static int cycx_x25_chan_connect(struct net_device *dev),
+	   cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb);
 
-static void chan_disconnect(struct net_device *dev),
-	    chan_x25_send_event(struct net_device *dev, u8 event);
+static void cycx_x25_chan_disconnect(struct net_device *dev),
+	    cycx_x25_chan_send_event(struct net_device *dev, u8 event);
 
 /* Miscellaneous functions */
-static void set_chan_state(struct net_device *dev, u8 state),
-	    chan_timer(unsigned long d);
+static void cycx_x25_set_chan_state(struct net_device *dev, u8 state),
+	    cycx_x25_chan_timer(unsigned long d);
 
 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble),
 	    reset_timer(struct net_device *dev);
@@ -182,20 +191,21 @@
 
 static unsigned dec_to_uint(u8 *str, int len);
 
-static struct net_device *get_dev_by_lcn(struct wan_device *wandev, s16 lcn);
-static struct net_device *get_dev_by_dte_addr(struct wan_device *wandev,
-					      char *dte);
+static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
+						  s16 lcn);
+static struct net_device *
+	cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte);
 
 #ifdef CYCLOMX_X25_DEBUG
 static void hex_dump(char *msg, unsigned char *p, int len);
-static void x25_dump_config(struct cycx_x25_config *conf);
-static void x25_dump_stats(struct cycx_x25_stats *stats);
-static void x25_dump_devs(struct wan_device *wandev);
+static void cycx_x25_dump_config(struct cycx_x25_config *conf);
+static void cycx_x25_dump_stats(struct cycx_x25_stats *stats);
+static void cycx_x25_dump_devs(struct wan_device *wandev);
 #else
 #define hex_dump(msg, p, len)
-#define x25_dump_config(conf)
-#define x25_dump_stats(stats)
-#define x25_dump_devs(wandev)
+#define cycx_x25_dump_config(conf)
+#define cycx_x25_dump_stats(stats)
+#define cycx_x25_dump_devs(wandev)
 #endif
 /* Public Functions */
 
@@ -208,7 +218,7 @@
  *
  * Return:	0	o.k.
  *		< 0	failure.  */
-int cyx_init(struct cycx_device *card, wandev_conf_t *conf)
+int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
 {
 	struct cycx_x25_config cfg;
 
@@ -306,7 +316,7 @@
 		cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
 
 	/* initialize adapter */
-	if (x25_configure(card, &cfg))
+	if (cycx_x25_configure(card, &cfg))
 		return -EIO;
 
 	/* Initialize protocol-specific fields of adapter data space */
@@ -314,11 +324,11 @@
 	card->wandev.interface	= conf->interface;
 	card->wandev.clocking	= conf->clocking;
 	card->wandev.station	= conf->station;
-	card->isr		= cyx_isr;
+	card->isr		= cycx_x25_irq_handler;
 	card->exec		= NULL;
-	card->wandev.update	= update;
-	card->wandev.new_if	= new_if;
-	card->wandev.del_if	= del_if;
+	card->wandev.update	= cycx_wan_update;
+	card->wandev.new_if	= cycx_wan_new_if;
+	card->wandev.del_if	= cycx_wan_del_if;
 	card->wandev.state	= WAN_DISCONNECTED;
 
 	return 0;
@@ -326,7 +336,7 @@
 
 /* WAN Device Driver Entry Points */
 /* Update device status & statistics. */
-static int update(struct wan_device *wandev)
+static int cycx_wan_update(struct wan_device *wandev)
 {
 	/* sanity checks */
 	if (!wandev || !wandev->private)
@@ -335,7 +345,7 @@
 	if (wandev->state == WAN_UNCONFIGURED)
 		return -ENODEV;
 
-	x25_get_stats(wandev->private);
+	cycx_x25_get_stats(wandev->private);
 
 	return 0;
 }
@@ -350,8 +360,8 @@
  *
  * Return:	0	o.k.
  *		< 0	failure (channel will not be created) */
-static int new_if(struct wan_device *wandev, struct net_device *dev,
-		  wanif_conf_t *conf)
+static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
+			   wanif_conf_t *conf)
 {
 	struct cycx_device *card = wandev->private;
 	struct cycx_x25_channel *chan;
@@ -402,8 +412,8 @@
 		chan->svc = 1;
 		strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
 		init_timer(&chan->timer);
-		chan->timer.function = chan_timer;
-		chan->timer.data = (unsigned long)dev;
+		chan->timer.function	= cycx_x25_chan_timer;
+		chan->timer.data	= (unsigned long)dev;
 
 		/* Set channel timeouts (default if not specified) */
 		chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
@@ -434,14 +444,14 @@
 
 	/* prepare network device data space for registration */
 	strcpy(dev->name, chan->name);
-	dev->init = if_init;
+	dev->init = cycx_netdevice_init;
 	dev->priv = chan;
 
 	return 0;
 }
 
 /* Delete logical channel. */
-static int del_if(struct wan_device *wandev, struct net_device *dev)
+static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev)
 {
 	if (dev->priv) {
 		struct cycx_x25_channel *chan = dev->priv;
@@ -467,43 +477,44 @@
  * This routine is called only once for each interface, during Linux network
  * interface registration.  Returning anything but zero will fail interface
  * registration. */
-static int if_init(struct net_device *dev)
+static int cycx_netdevice_init(struct net_device *dev)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 	struct cycx_device *card = chan->card;
 	struct wan_device *wandev = &card->wandev;
 
 	/* Initialize device driver entry points */
-	dev->open = if_open;
-	dev->stop = if_close;
-	dev->hard_header = if_header;
-	dev->rebuild_header = if_rebuild_hdr;
-	dev->hard_start_xmit = if_send;
-	dev->get_stats = if_stats;
+	dev->open		= cycx_netdevice_open;
+	dev->stop		= cycx_netdevice_stop;
+	dev->hard_header	= cycx_netdevice_hard_header;
+	dev->rebuild_header	= cycx_netdevice_rebuild_header;
+	dev->hard_start_xmit	= cycx_netdevice_hard_start_xmit;
+	dev->get_stats		= cycx_netdevice_get_stats;
 
 	/* Initialize media-specific parameters */
-	dev->mtu = X25_CHAN_MTU;
-	dev->type = ARPHRD_HWX25;	/* ARP h/w type */
-	dev->hard_header_len = 0;	/* media header length */
-	dev->addr_len = 0;		/* hardware address length */
+	dev->mtu		= CYCX_X25_CHAN_MTU;
+	dev->type		= ARPHRD_HWX25;	/* ARP h/w type */
+	dev->hard_header_len	= 0;		/* media header length */
+	dev->addr_len		= 0;		/* hardware address length */
 
 	if (!chan->svc)
 		*(u16*)dev->dev_addr = htons(chan->lcn);
 
 	/* Initialize hardware parameters (just for reference) */
-	dev->irq = wandev->irq;
-	dev->dma = wandev->dma;
-	dev->base_addr = wandev->ioport;
-	dev->mem_start = (unsigned long)wandev->maddr;
-	dev->mem_end = (unsigned long)(wandev->maddr + wandev->msize - 1);
-	dev->flags |= IFF_NOARP;
+	dev->irq		= wandev->irq;
+	dev->dma		= wandev->dma;
+	dev->base_addr		= wandev->ioport;
+	dev->mem_start		= (unsigned long)wandev->maddr;
+	dev->mem_end		= (unsigned long)(wandev->maddr +
+						  wandev->msize - 1);
+	dev->flags		|= IFF_NOARP;
 
 	/* Set transmit buffer queue length */
-	dev->tx_queue_len = 10;
+	dev->tx_queue_len	= 10;
 	SET_MODULE_OWNER(dev);
 
 	/* Initialize socket buffers */
-	set_chan_state(dev, WAN_DISCONNECTED);
+	cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
 
 	return 0;
 }
@@ -513,7 +524,7 @@
  * o if link is disconnected then initiate connection
  *
  * Return 0 if O.k. or errno.  */
-static int if_open(struct net_device *dev)
+static int cycx_netdevice_open(struct net_device *dev)
 {
 	if (netif_running(dev))
 		return -EBUSY; /* only one open is allowed */
@@ -525,14 +536,14 @@
 /* Close network interface.
  * o reset flags.
  * o if there's no more open channels then disconnect physical link. */
-static int if_close(struct net_device *dev)
+static int cycx_netdevice_stop(struct net_device *dev)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 
 	netif_stop_queue(dev);
 
 	if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
-		chan_disconnect(dev);
+		cycx_x25_chan_disconnect(dev);
 
 	return 0;
 }
@@ -545,8 +556,9 @@
  * set skb->protocol to 0 and discard packet later.
  *
  * Return:	media header length. */
-static int if_header(struct sk_buff *skb, struct net_device *dev,
-		      u16 type, void *daddr, void *saddr, unsigned len)
+static int cycx_netdevice_hard_header(struct sk_buff *skb,
+				      struct net_device *dev, u16 type,
+				      void *daddr, void *saddr, unsigned len)
 {
 	skb->protocol = type;
 
@@ -556,7 +568,7 @@
 /* * Re-build media header.
  * Return:	1	physical address resolved.
  *		0	physical address not resolved */
-static int if_rebuild_hdr(struct sk_buff *skb)
+static int cycx_netdevice_rebuild_header(struct sk_buff *skb)
 {
 	return 1;
 }
@@ -576,7 +588,8 @@
  *    bottom half" (with interrupts enabled).
  * 2. Setting tbusy flag will inhibit further transmit requests from the
  *    protocol stack and can be used for flow control with protocol layer. */
-static int if_send(struct sk_buff *skb, struct net_device *dev)
+static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
+					  struct net_device *dev)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 	struct cycx_device *card = chan->card;
@@ -595,7 +608,7 @@
 	} else if (chan->protocol == ETH_P_IP) {
 		switch (chan->state) {
 		case WAN_DISCONNECTED:
-			if (chan_connect(dev)) {
+			if (cycx_x25_chan_connect(dev)) {
 				netif_stop_queue(dev);
 				return -EBUSY;
 			}
@@ -605,7 +618,7 @@
 			dev->trans_start = jiffies;
 			netif_stop_queue(dev);
 
-			if (chan_send(dev, skb))
+			if (cycx_x25_chan_send(dev, skb))
 				return -EBUSY;
 
 			break;
@@ -617,10 +630,10 @@
 		switch (skb->data[0]) {
 		case 0: break;
 		case 1: /* Connect request */
-			chan_connect(dev);
+			cycx_x25_chan_connect(dev);
 			goto free_packet;
 		case 2: /* Disconnect request */
-			chan_disconnect(dev);
+			cycx_x25_chan_disconnect(dev);
 			goto free_packet;
 	        default:
 			printk(KERN_INFO
@@ -635,7 +648,7 @@
 		dev->trans_start = jiffies;
 		netif_stop_queue(dev);
 
-		if (chan_send(dev, skb)) {
+		if (cycx_x25_chan_send(dev, skb)) {
 			/* prepare for future retransmissions */
 			skb_push(skb, 1);
 			return -EBUSY;
@@ -650,7 +663,7 @@
 
 /* Get Ethernet-style interface statistics.
  * Return a pointer to struct net_device_stats */
-static struct net_device_stats *if_stats(struct net_device *dev)
+static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 
@@ -659,7 +672,7 @@
 
 /* Interrupt Handlers */
 /* X.25 Interrupt Service Routine. */
-static void cyx_isr(struct cycx_device *card)
+static void cycx_x25_irq_handler(struct cycx_device *card)
 {
 	struct cycx_x25_cmd cmd;
 	u16 z = 0;
@@ -670,37 +683,38 @@
 
 	switch (cmd.command) {
 	case X25_DATA_INDICATION:
-		rx_intr(card, &cmd);
+		cycx_x25_irq_rx(card, &cmd);
 		break;
 	case X25_ACK_FROM_VC:
-		tx_intr(card, &cmd);
+		cycx_x25_irq_tx(card, &cmd);
 		break;
 	case X25_LOG:
-		log_intr(card, &cmd);
+		cycx_x25_irq_log(card, &cmd);
 		break;
 	case X25_STATISTIC:
-		stat_intr(card, &cmd);
+		cycx_x25_irq_stat(card, &cmd);
 		break;
 	case X25_CONNECT_CONFIRM:
-		connect_confirm_intr(card, &cmd);
+		cycx_x25_irq_connect_confirm(card, &cmd);
 		break;
 	case X25_CONNECT_INDICATION:
-		connect_intr(card, &cmd);
+		cycx_x25_irq_connect(card, &cmd);
 		break;
 	case X25_DISCONNECT_INDICATION:
-		disconnect_intr(card, &cmd);
+		cycx_x25_irq_disconnect(card, &cmd);
 		break;
 	case X25_DISCONNECT_CONFIRM:
-		disconnect_confirm_intr(card, &cmd);
+		cycx_x25_irq_disconnect_confirm(card, &cmd);
 		break;
 	case X25_LINE_ON:
-		cyclomx_set_state(card, WAN_CONNECTED);
+		cycx_set_state(card, WAN_CONNECTED);
 		break;
 	case X25_LINE_OFF:
-		cyclomx_set_state(card, WAN_DISCONNECTED);
+		cycx_set_state(card, WAN_DISCONNECTED);
 		break;
 	default:
-		spur_intr(card, &cmd); /* unwanted interrupt */
+		cycx_x25_irq_spurious(card, &cmd);
+		break;
 	}
 
 	cycx_poke(&card->hw, 0, &z, sizeof(z));
@@ -711,7 +725,7 @@
 /* Transmit interrupt handler.
  *	o Release socket buffer
  *	o Clear 'tbusy' flag */
-static void tx_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 {
 	struct net_device *dev;
 	struct wan_device *wandev = &card->wandev;
@@ -720,7 +734,8 @@
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
 
 	/* unbusy device and then dev_tint(); */
-	if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
+	dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
+	if (dev) {
 		card->buff_int_mode_unbusy = 1;
 		netif_wake_queue(dev);
 	} else
@@ -742,7 +757,7 @@
  *    expected on this channel.
  * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
  *    socket buffers available) the whole packet sequence must be discarded. */
-static void rx_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 {
 	struct wan_device *wandev = &card->wandev;
 	struct net_device *dev;
@@ -755,7 +770,8 @@
 	cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm));
 	bitm &= 0x10;
 
-	if ((dev = get_dev_by_lcn(wandev, lcn)) == NULL) {
+	dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
+	if (!dev) {
 		/* Invalid channel, discard packet */
 		printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
 				 card->devname, lcn);
@@ -826,7 +842,8 @@
 }
 
 /* Connect interrupt handler. */
-static void connect_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_connect(struct cycx_device *card,
+				 struct cycx_x25_cmd *cmd)
 {
 	struct wan_device *wandev = &card->wandev;
 	struct net_device *dev = NULL;
@@ -851,10 +868,11 @@
 	if (sizerem)
 		nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
 
-	dprintk(1, KERN_INFO "connect_intr:lcn=%d, local=%s, remote=%s\n",
-			  lcn, loc, rem);
+	dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n",
+			  __FUNCTION__, lcn, loc, rem);
 
-	if ((dev = get_dev_by_dte_addr(wandev, rem)) == NULL) {
+	dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
+	if (!dev) {
 		/* Invalid channel, discard packet */
 		printk(KERN_INFO "%s: connect not expected: remote %s!\n",
 				 card->devname, rem);
@@ -863,13 +881,13 @@
 
 	chan = dev->priv;
 	chan->lcn = lcn;
-	x25_connect_response(card, chan);
-	set_chan_state(dev, WAN_CONNECTED);
+	cycx_x25_connect_response(card, chan);
+	cycx_x25_set_chan_state(dev, WAN_CONNECTED);
 }
 
 /* Connect confirm interrupt handler. */
-static void connect_confirm_intr(struct cycx_device *card,
-				 struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
+					 struct cycx_x25_cmd *cmd)
 {
 	struct wan_device *wandev = &card->wandev;
 	struct net_device *dev;
@@ -878,10 +896,11 @@
 
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
 	cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
-	dprintk(1, KERN_INFO "%s: connect_confirm_intr:lcn=%d, key=%d\n",
-			  card->devname, lcn, key);
+	dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n",
+			  card->devname, __FUNCTION__, lcn, key);
 
-	if ((dev = get_dev_by_lcn(wandev, -key)) == NULL) {
+	dev = cycx_x25_get_dev_by_lcn(wandev, -key);
+	if (!dev) {
 		/* Invalid channel, discard packet */
 		clear_bit(--key, (void*)&card->u.x.connection_keys);
 		printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
@@ -892,51 +911,54 @@
 	clear_bit(--key, (void*)&card->u.x.connection_keys);
 	chan = dev->priv;
 	chan->lcn = lcn;
-	set_chan_state(dev, WAN_CONNECTED);
+	cycx_x25_set_chan_state(dev, WAN_CONNECTED);
 }
 
 /* Disconnect confirm interrupt handler. */
-static void disconnect_confirm_intr(struct cycx_device *card,
-				    struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
+					    struct cycx_x25_cmd *cmd)
 {
 	struct wan_device *wandev = &card->wandev;
 	struct net_device *dev;
 	u8 lcn;
 
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
-	dprintk(1, KERN_INFO "%s: disconnect_confirm_intr:lcn=%d\n",
-			  card->devname, lcn);
-	if ((dev = get_dev_by_lcn(wandev, lcn)) == NULL) {
+	dprintk(1, KERN_INFO "%s: %s:lcn=%d\n",
+			  card->devname, __FUNCTION__, lcn);
+	dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
+	if (!dev) {
 		/* Invalid channel, discard packet */
 		printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
 				 card->devname, lcn);
 		return;
 	}
 
-	set_chan_state(dev, WAN_DISCONNECTED);
+	cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
 }
 
 /* disconnect interrupt handler. */
-static void disconnect_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_disconnect(struct cycx_device *card,
+				    struct cycx_x25_cmd *cmd)
 {
 	struct wan_device *wandev = &card->wandev;
 	struct net_device *dev;
 	u8 lcn;
 
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
-	dprintk(1, KERN_INFO "disconnect_intr:lcn=%d\n", lcn);
+	dprintk(1, KERN_INFO "%s:lcn=%d\n", __FUNCTION__, lcn);
 
-	if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
+	dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
+	if (dev) {
 		struct cycx_x25_channel *chan = dev->priv;
 
-		x25_disconnect_response(card, chan->link, lcn);
-		set_chan_state(dev, WAN_DISCONNECTED);
+		cycx_x25_disconnect_response(card, chan->link, lcn);
+		cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
 	} else
-		x25_disconnect_response(card, 0, lcn);
+		cycx_x25_disconnect_response(card, 0, lcn);
 }
 
 /* LOG interrupt handler. */
-static void log_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 {
 #if CYCLOMX_X25_DEBUG
 	char bf[20];
@@ -952,7 +974,7 @@
 	cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
 	cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
 
-	printk(KERN_INFO "cyx_isr: X25_LOG (0x4500) indic.:\n");
+	printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
 	printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
 	printk(KERN_INFO "Log message code=0x%X\n", msg_code);
 	printk(KERN_INFO "Link=%d\n", link);
@@ -964,20 +986,22 @@
 }
 
 /* STATISTIC interrupt handler. */
-static void stat_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_stat(struct cycx_device *card,
+			      struct cycx_x25_cmd *cmd)
 {
 	cycx_peek(&card->hw, cmd->buf, &card->u.x.stats,
 		  sizeof(card->u.x.stats));
-	hex_dump("stat_intr", (unsigned char*)&card->u.x.stats,
+	hex_dump("cycx_x25_irq_stat", (unsigned char*)&card->u.x.stats,
 		 sizeof(card->u.x.stats));
-	x25_dump_stats(&card->u.x.stats);
+	cycx_x25_dump_stats(&card->u.x.stats);
 	wake_up_interruptible(&card->wait_stats);
 }
 
 /* Spurious interrupt handler.
  * o print a warning
  * If number of spurious interrupts exceeded some limit, then ??? */
-static void spur_intr(struct cycx_device *card, struct cycx_x25_cmd *cmd)
+static void cycx_x25_irq_spurious(struct cycx_device *card,
+				  struct cycx_x25_cmd *cmd)
 {
 	printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
 			 card->devname, cmd->command);
@@ -1008,7 +1032,7 @@
 	struct cycx_x25_cmd c;
 	unsigned long flags;
 	u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
-	u8 retry = MAX_CMD_RETRY;
+	u8 retry = CYCX_X25_MAX_CMD_RETRY;
 	int err = 0;
 
 	c.command = command;
@@ -1050,7 +1074,8 @@
 }
 
 /* Configure adapter. */
-static int x25_configure(struct cycx_device *card, struct cycx_x25_config *conf)
+static int cycx_x25_configure(struct cycx_device *card,
+			      struct cycx_x25_config *conf)
 {
 	struct {
 		u16 nlinks;
@@ -1071,15 +1096,15 @@
 	x25_cmd_conf.conf[1].clock = 8;
 	x25_cmd_conf.conf[1].flags = 0; /* default = RS232 */
 
-	x25_dump_config(&x25_cmd_conf.conf[0]);
-	x25_dump_config(&x25_cmd_conf.conf[1]);
+	cycx_x25_dump_config(&x25_cmd_conf.conf[0]);
+	cycx_x25_dump_config(&x25_cmd_conf.conf[1]);
 
 	return x25_exec(card, X25_CONFIG, 0,
 			&x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0);
 }
 
 /* Get protocol statistics. */
-static int x25_get_stats(struct cycx_device *card)
+static int cycx_x25_get_stats(struct cycx_device *card)
 {
 	/* the firmware expects 20 in the size field!!!
 	   thanks to Daniela */
@@ -1107,7 +1132,7 @@
 	card->wandev.stats.collisions = 0; /* not available from fw */
 	card->wandev.stats.tx_errors = 0; /* not available from fw */
 
-	x25_dump_devs(&card->wandev);
+	cycx_x25_dump_devs(&card->wandev);
 
 	return 0;
 }
@@ -1207,8 +1232,8 @@
 }
 
 /* Place X.25 CONNECT RESPONSE. */
-static int x25_connect_response(struct cycx_device *card,
-				struct cycx_x25_channel *chan)
+static int cycx_x25_connect_response(struct cycx_device *card,
+				     struct cycx_x25_channel *chan)
 {
 	u8 d[8];
 
@@ -1222,7 +1247,8 @@
 }
 
 /* Place X.25 DISCONNECT RESPONSE.  */
-static int x25_disconnect_response(struct cycx_device *card, u8 link, u8 lcn)
+static int cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
+					u8 lcn)
 {
 	char d[5];
 
@@ -1251,8 +1277,8 @@
 }
 
 /* Send X.25 data packet. */
-static int x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm, int len,
-		    void *buf)
+static int cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
+			 int len, void *buf)
 {
 	u8 d[] = "?\xFF\x10??";
 
@@ -1264,7 +1290,8 @@
 
 /* Miscellaneous */
 /* Find network device by its channel number.  */
-static struct net_device *get_dev_by_lcn(struct wan_device *wandev, s16 lcn)
+static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
+						  s16 lcn)
 {
 	struct net_device *dev = wandev->dev;
 	struct cycx_x25_channel *chan;
@@ -1280,8 +1307,8 @@
 }
 
 /* Find network device by its remote dte address. */
-static struct net_device *get_dev_by_dte_addr(struct wan_device *wandev,
-					      char *dte)
+static struct net_device *
+	cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte)
 {
 	struct net_device *dev = wandev->dev;
 	struct cycx_x25_channel *chan;
@@ -1303,7 +1330,7 @@
  * Return:	0	connected
  *		>0	connection in progress
  *		<0	failure */
-static int chan_connect(struct net_device *dev)
+static int cycx_x25_chan_connect(struct net_device *dev)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 	struct cycx_device *card = chan->card;
@@ -1318,42 +1345,42 @@
 		if (x25_place_call(card, chan))
 			return -EIO;
 
-		set_chan_state(dev, WAN_CONNECTING);
+		cycx_x25_set_chan_state(dev, WAN_CONNECTING);
 		return 1;
 	} else
-		set_chan_state(dev, WAN_CONNECTED);
+		cycx_x25_set_chan_state(dev, WAN_CONNECTED);
 
 	return 0;
 }
 
 /* Disconnect logical channel.
  * o if SVC then clear X.25 call */
-static void chan_disconnect(struct net_device *dev)
+static void cycx_x25_chan_disconnect(struct net_device *dev)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 
 	if (chan->svc) {
 		x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
-		set_chan_state(dev, WAN_DISCONNECTING);
+		cycx_x25_set_chan_state(dev, WAN_DISCONNECTING);
 	} else
-		set_chan_state(dev, WAN_DISCONNECTED);
+		cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
 }
 
 /* Called by kernel timer */
-static void chan_timer(unsigned long d)
+static void cycx_x25_chan_timer(unsigned long d)
 {
 	struct net_device *dev = (struct net_device *)d;
 	struct cycx_x25_channel *chan = dev->priv;
 
 	if (chan->state == WAN_CONNECTED)
-		chan_disconnect(dev);
+		cycx_x25_chan_disconnect(dev);
 	else
-		printk(KERN_ERR "%s: chan_timer for svc (%s) not connected!\n",
-				chan->card->devname, dev->name);
+		printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
+				chan->card->devname, __FUNCTION__, dev->name);
 }
 
 /* Set logical channel state. */
-static void set_chan_state(struct net_device *dev, u8 state)
+static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 	struct cycx_device *card = chan->card;
@@ -1374,7 +1401,7 @@
 			reset_timer(dev);
 
 			if (chan->protocol == ETH_P_X25)
-				chan_x25_send_event(dev, 1);
+				cycx_x25_chan_send_event(dev, 1);
 
 			break;
 		case WAN_CONNECTING:
@@ -1392,7 +1419,7 @@
 			}
 
 			if (chan->protocol == ETH_P_X25)
-				chan_x25_send_event(dev, 2);
+				cycx_x25_chan_send_event(dev, 2);
 
 			netif_wake_queue(dev);
 			break;
@@ -1419,7 +1446,7 @@
  *    the packet into 'complete sequence' using M-bit.
  * 2. When transmission is complete, an event notification should be issued
  *    to the router.  */
-static int chan_send(struct net_device *dev, struct sk_buff *skb)
+static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb)
 {
 	struct cycx_x25_channel *chan = dev->priv;
 	struct cycx_device *card = chan->card;
@@ -1431,7 +1458,7 @@
 		bitm = 0x10;		/* set M-bit (more data) */
 	}
 
-	if (x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
+	if (cycx_x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
 		return 1;
 
 	if (bitm) {
@@ -1447,7 +1474,7 @@
 
 /* Send event (connection, disconnection, etc) to X.25 socket layer */
 
-static void chan_x25_send_event(struct net_device *dev, u8 event)
+static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
 {
 	struct sk_buff *skb;
 	unsigned char *ptr;
@@ -1525,7 +1552,7 @@
 		mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ);
 }
 #ifdef CYCLOMX_X25_DEBUG
-static void x25_dump_config(struct cycx_x25_config *conf)
+static void cycx_x25_dump_config(struct cycx_x25_config *conf)
 {
 	printk(KERN_INFO "X.25 configuration\n");
 	printk(KERN_INFO "-----------------\n");
@@ -1547,7 +1574,7 @@
 	printk(KERN_INFO "flags=0x%x\n", conf->flags);
 }
 
-static void x25_dump_stats(struct cycx_x25_stats *stats)
+static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
 {
 	printk(KERN_INFO "X.25 statistics\n");
 	printk(KERN_INFO "--------------\n");
@@ -1563,7 +1590,7 @@
 	printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
 }
 
-static void x25_dump_devs(struct wan_device *wandev)
+static void cycx_x25_dump_devs(struct wan_device *wandev)
 {
 	struct net_device *dev = wandev->dev;
 
diff -urN linux-2.5.69-bk14/drivers/net/wan/sdla.c linux-2.5.69-bk15/drivers/net/wan/sdla.c
--- linux-2.5.69-bk14/drivers/net/wan/sdla.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/sdla.c	2003-05-21 04:47:33.000000000 -0700
@@ -1636,9 +1636,10 @@
 	dev->change_mtu		= sdla_change_mtu;
 
 	dev->type		= 0xFFFF;
-	dev->hard_header_len = 0;
+	dev->hard_header_len	= 0;
 	dev->addr_len		= 0;
 	dev->mtu		= SDLA_MAX_MTU;
+	SET_MODULE_OWNER(dev);
 
 	flp->activate		= sdla_activate;
 	flp->deactivate		= sdla_deactivate;
diff -urN linux-2.5.69-bk14/drivers/net/wan/sdla_chdlc.c linux-2.5.69-bk15/drivers/net/wan/sdla_chdlc.c
--- linux-2.5.69-bk14/drivers/net/wan/sdla_chdlc.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/sdla_chdlc.c	2003-05-21 04:47:33.000000000 -0700
@@ -914,7 +914,6 @@
 	dev->get_stats		= &if_stats;
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-
 	
 	/* Initialize media-specific parameters */
 	dev->flags		|= IFF_POINTOPOINT;
@@ -951,6 +950,7 @@
          * by stack.
 	 */
         dev->tx_queue_len = 100;
+	SET_MODULE_OWNER(dev);
    
 	return 0;
 }
diff -urN linux-2.5.69-bk14/drivers/net/wan/sdla_fr.c linux-2.5.69-bk15/drivers/net/wan/sdla_fr.c
--- linux-2.5.69-bk14/drivers/net/wan/sdla_fr.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/sdla_fr.c	2003-05-21 04:47:33.000000000 -0700
@@ -1187,6 +1187,7 @@
 	dev->base_addr	= wandev->ioport;
 	dev->mem_start	= wandev->maddr;
 	dev->mem_end	= wandev->maddr + wandev->msize - 1;
+	SET_MODULE_OWNER(dev);
 
 	return 0;
 }
diff -urN linux-2.5.69-bk14/drivers/net/wan/sdla_ppp.c linux-2.5.69-bk15/drivers/net/wan/sdla_ppp.c
--- linux-2.5.69-bk14/drivers/net/wan/sdla_ppp.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/sdla_ppp.c	2003-05-21 04:47:33.000000000 -0700
@@ -722,6 +722,7 @@
 
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 100;
+	SET_MODULE_OWNER(dev);
    
 	return 0;
 }
diff -urN linux-2.5.69-bk14/drivers/net/wan/sdla_x25.c linux-2.5.69-bk15/drivers/net/wan/sdla_x25.c
--- linux-2.5.69-bk14/drivers/net/wan/sdla_x25.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/wan/sdla_x25.c	2003-05-21 04:47:33.000000000 -0700
@@ -1148,6 +1148,7 @@
 
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 100;
+	SET_MODULE_OWNER(dev);
 
 	/* FIXME Why are we doing this */
 	set_chan_state(dev, WAN_DISCONNECTED);
diff -urN linux-2.5.69-bk14/drivers/net/yellowfin.c linux-2.5.69-bk15/drivers/net/yellowfin.c
--- linux-2.5.69-bk14/drivers/net/yellowfin.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/net/yellowfin.c	2003-05-21 04:47:33.000000000 -0700
@@ -444,6 +444,7 @@
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	np = dev->priv;
 
diff -urN linux-2.5.69-bk14/drivers/usb/core/hcd.c linux-2.5.69-bk15/drivers/usb/core/hcd.c
--- linux-2.5.69-bk14/drivers/usb/core/hcd.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/core/hcd.c	2003-05-21 04:47:34.000000000 -0700
@@ -324,6 +324,7 @@
 	const u8	*bufp = 0;
 	u8		*ubuf = urb->transfer_buffer;
 	int		len = 0;
+	unsigned long	flags;
 
 	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
 	wValue   = le16_to_cpu (cmd->wValue);
@@ -436,7 +437,9 @@
 	}
 
 	/* any errors get returned through the urb completion */
+	local_irq_save (flags);
 	usb_hcd_giveback_urb (hcd, urb, NULL);
+	local_irq_restore (flags);
 	return 0;
 }
 
@@ -454,20 +457,22 @@
 	int	len = 1 + (urb->dev->maxchild / 8);
 
 	/* rh_timer protected by hcd_data_lock */
-	if (timer_pending (&hcd->rh_timer)
+	if (hcd->rh_timer.data
 			|| urb->status != -EINPROGRESS
 			|| urb->transfer_buffer_length < len) {
-		dev_dbg (hcd->controller, "not queuing status urb, stat %d\n", urb->status);
+		dev_dbg (hcd->controller,
+				"not queuing rh status urb, stat %d\n",
+				urb->status);
 		return -EINVAL;
 	}
 
-	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
 	init_timer (&hcd->rh_timer);
 	hcd->rh_timer.function = rh_report_status;
 	hcd->rh_timer.data = (unsigned long) urb;
 	/* USB 2.0 spec says 256msec; this is close enough */
 	hcd->rh_timer.expires = jiffies + HZ/4;
 	add_timer (&hcd->rh_timer);
+	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
 	return 0;
 }
 
@@ -481,39 +486,37 @@
 	unsigned long	flags;
 
 	urb = (struct urb *) ptr;
-	spin_lock_irqsave (&urb->lock, flags);
-	if (!urb->dev) {
-		spin_unlock_irqrestore (&urb->lock, flags);
+	local_irq_save (flags);
+	spin_lock (&urb->lock);
+
+	/* do nothing if the hc is gone or the urb's been unlinked */
+	if (!urb->dev
+			|| urb->status != -EINPROGRESS
+			|| (hcd = urb->dev->bus->hcpriv) == 0
+			|| !HCD_IS_RUNNING (hcd->state)) {
+		spin_unlock (&urb->lock);
+		local_irq_restore (flags);
 		return;
 	}
 
-	hcd = urb->dev->bus->hcpriv;
-	if (urb->status == -EINPROGRESS) {
-		if (HCD_IS_RUNNING (hcd->state)) {
-			length = hcd->driver->hub_status_data (hcd,
-					urb->transfer_buffer);
-			spin_unlock_irqrestore (&urb->lock, flags);
-			if (length > 0) {
-				urb->actual_length = length;
-				urb->status = 0;
-				urb->hcpriv = 0;
-				urb->complete (urb, NULL);
-				return;
-			}
-		} else
-			spin_unlock_irqrestore (&urb->lock, flags);
+	length = hcd->driver->hub_status_data (hcd, urb->transfer_buffer);
 
-		/* retrigger timer until completion:  success or unlink */
-		spin_lock_irqsave (&hcd_data_lock, flags);
-		rh_status_urb (hcd, urb);
-		spin_unlock_irqrestore (&hcd_data_lock, flags);
-	} else {
-		/* this urb's been unlinked */
+	/* complete the status urb, or retrigger the timer */
+	spin_lock (&hcd_data_lock);
+	if (length > 0) {
+		hcd->rh_timer.data = 0;
+		urb->actual_length = length;
+		urb->status = 0;
 		urb->hcpriv = 0;
-		spin_unlock_irqrestore (&urb->lock, flags);
+	} else
+		mod_timer (&hcd->rh_timer, jiffies + HZ/4);
+	spin_unlock (&hcd_data_lock);
+	spin_unlock (&urb->lock);
 
+	/* local irqs are always blocked in completions */
+	if (length > 0)
 		usb_hcd_giveback_urb (hcd, urb, NULL);
-	}
+	local_irq_restore (flags);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -541,13 +544,14 @@
 {
 	unsigned long	flags;
 
-	spin_lock_irqsave (&hcd_data_lock, flags);
+	/* note:  always a synchronous unlink */
 	del_timer_sync (&hcd->rh_timer);
 	hcd->rh_timer.data = 0;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
 
-	/* we rely on RH callback code not unlinking its URB! */
+	local_irq_save (flags);
+	urb->hcpriv = 0;
 	usb_hcd_giveback_urb (hcd, urb, NULL);
+	local_irq_restore (flags);
 }
 
 /*-------------------------------------------------------------------------*/
diff -urN linux-2.5.69-bk14/drivers/usb/core/hub.c linux-2.5.69-bk15/drivers/usb/core/hub.c
--- linux-2.5.69-bk14/drivers/usb/core/hub.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/core/hub.c	2003-05-21 04:47:34.000000000 -0700
@@ -42,7 +42,7 @@
 static LIST_HEAD(hub_list);		/* List of all hubs (for cleanup) */
 
 static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
-static int khubd_pid = 0;			/* PID of khubd */
+static pid_t khubd_pid = 0;			/* PID of khubd */
 static DECLARE_COMPLETION(khubd_exited);
 
 #ifdef	DEBUG
@@ -1126,7 +1126,7 @@
  */
 int usb_hub_init(void)
 {
-	int pid;
+	pid_t pid;
 
 	if (usb_register(&hub_driver) < 0) {
 		err("Unable to register USB hub driver");
diff -urN linux-2.5.69-bk14/drivers/usb/core/message.c linux-2.5.69-bk15/drivers/usb/core/message.c
--- linux-2.5.69-bk14/drivers/usb/core/message.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/core/message.c	2003-05-21 04:47:34.000000000 -0700
@@ -795,6 +795,7 @@
 	struct usb_interface *iface;
 	struct usb_host_interface *iface_as;
 	int i, ret;
+	void (*disable)(struct usb_device *, int) = dev->bus->op->disable;
 
 	iface = usb_ifnum_to_if(dev, interface);
 	if (!iface) {
@@ -832,9 +833,11 @@
 		u8	ep = iface_as->endpoint [i].desc.bEndpointAddress;
 		int	out = !(ep & USB_DIR_IN);
 
+		/* clear out hcd state, then usbcore state */
+		if (disable)
+			disable (dev, ep);
 		ep &= USB_ENDPOINT_NUMBER_MASK;
 		(out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0;
-		// FIXME want hcd hook here, "no such endpoint"
 	}
 	iface->act_altsetting = alternate;
 
@@ -898,6 +901,7 @@
 {
 	int i, ret;
 	struct usb_host_config *cp = NULL;
+	void (*disable)(struct usb_device *, int) = dev->bus->op->disable;
 	
 	for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
 		if (dev->config[i].desc.bConfigurationValue == configuration) {
@@ -911,11 +915,15 @@
 	}
 
 	/* if it's already configured, clear out old state first. */
-	if (dev->state != USB_STATE_ADDRESS) {
-		/* FIXME unbind drivers from all "old" interfaces.
-		 * handshake with hcd to reset cached hc endpoint state.
-		 */
+	if (dev->state != USB_STATE_ADDRESS && disable) {
+		for (i = 0; i < 15; i++) {
+			disable (dev, i);
+			disable (dev, USB_DIR_IN | i);
+		}
 	}
+	dev->toggle[0] = dev->toggle[1] = 0;
+	dev->halted[0] = dev->halted[1] = 0;
+	dev->state = USB_STATE_ADDRESS;
 
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
@@ -923,15 +931,9 @@
 		return ret;
 	if (configuration)
 		dev->state = USB_STATE_CONFIGURED;
-	else
-		dev->state = USB_STATE_ADDRESS;
 	dev->actconfig = cp;
 
 	/* reset more hc/hcd endpoint state */
-	dev->toggle[0] = 0;
-	dev->toggle[1] = 0;
-	dev->halted[0] = 0;
-	dev->halted[1] = 0;
 	usb_set_maxpacket(dev);
 
 	return 0;
diff -urN linux-2.5.69-bk14/drivers/usb/gadget/net2280.c linux-2.5.69-bk15/drivers/usb/gadget/net2280.c
--- linux-2.5.69-bk14/drivers/usb/gadget/net2280.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/gadget/net2280.c	2003-05-21 04:47:34.000000000 -0700
@@ -2642,7 +2642,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static const struct pci_device_id __devinitdata pci_ids [] = { {
+static struct pci_device_id __devinitdata pci_ids [] = { {
 	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
 	.class_mask = 	~0,
 	.vendor =	0x17cc,
diff -urN linux-2.5.69-bk14/drivers/usb/host/ehci-q.c linux-2.5.69-bk15/drivers/usb/host/ehci-q.c
--- linux-2.5.69-bk14/drivers/usb/host/ehci-q.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/host/ehci-q.c	2003-05-21 04:47:34.000000000 -0700
@@ -918,11 +918,11 @@
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_next.qh = 0;
 	qh_put (ehci, qh);			// refcount from reclaim 
-	ehci->reclaim = 0;
-	ehci->reclaim_ready = 0;
 
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
 	next = qh->reclaim;
+	ehci->reclaim = next;
+	ehci->reclaim_ready = 0;
 	qh->reclaim = 0;
 
 	qh_completions (ehci, qh, regs);
@@ -941,8 +941,10 @@
 			timer_action (ehci, TIMER_ASYNC_OFF);
 	}
 
-	if (next)
+	if (next) {
+		ehci->reclaim = 0;
 		start_unlink_async (ehci, next);
+	}
 }
 
 /* makes sure the async qh will become idle */
@@ -1046,7 +1048,8 @@
 			if (list_empty (&qh->qtd_list)) {
 				if (qh->stamp == ehci->stamp)
 					action = TIMER_ASYNC_SHRINK;
-				else if (!ehci->reclaim)
+				else if (!ehci->reclaim
+					    && qh->qh_state == QH_STATE_LINKED)
 					start_unlink_async (ehci, qh);
 			}
 
diff -urN linux-2.5.69-bk14/drivers/usb/misc/speedtch.c linux-2.5.69-bk15/drivers/usb/misc/speedtch.c
--- linux-2.5.69-bk14/drivers/usb/misc/speedtch.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/misc/speedtch.c	2003-05-21 04:47:34.000000000 -0700
@@ -77,18 +77,20 @@
 #include <linux/init.h>
 
 /*
-#define DEBUG 1
-#define DEBUG_PACKET 1
+#define DEBUG
+#define VERBOSE_DEBUG
 */
 
 #include <linux/usb.h>
 
 
-#ifdef DEBUG_PACKET
+#ifdef VERBOSE_DEBUG
 static int udsl_print_packet (const unsigned char *data, int len);
-#define PACKETDEBUG(arg...) udsl_print_packet (arg)
+#define PACKETDEBUG(arg...)	udsl_print_packet (arg)
+#define vdbg(arg...)		dbg (arg)
 #else
 #define PACKETDEBUG(arg...)
+#define vdbg(arg...)
 #endif
 
 #define DRIVER_AUTHOR	"Johan Verrept, Duncan Sands <duncan.sands@wanadoo.fr>"
@@ -265,7 +267,7 @@
 	struct udsl_vcc_data *vcc;
 
 	list_for_each_entry (vcc, &instance->vcc_list, list)
-		if ((vcc->vpi == vpi) && (vcc->vci == vci))
+		if ((vcc->vci == vci) && (vcc->vpi == vpi))
 			return vcc;
 	return NULL;
 }
@@ -287,8 +289,8 @@
 		vpi = ((cell[0] & 0x0f) << 4) | (cell[1] >> 4);
 		vci = ((cell[1] & 0x0f) << 12) | (cell[2] << 4) | (cell[3] >> 4);
 
-		dbg ("udsl_decode_rawcell (0x%p, 0x%p, 0x%p) called", instance, skb, ctx);
-		dbg ("udsl_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail);
+		vdbg ("udsl_decode_rawcell (0x%p, 0x%p, 0x%p) called", instance, skb, ctx);
+		vdbg ("udsl_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail);
 
 		/* here should the header CRC check be... */
 
@@ -296,7 +298,7 @@
 			dbg ("udsl_decode_rawcell: no vcc found for packet on vpi %d, vci %d", vpi, vci);
 			__skb_pull (skb, min (skb->len, (unsigned) 53));
 		} else {
-			dbg ("udsl_decode_rawcell found vcc %p for packet on vpi %d, vci %d", vcc, vpi, vci);
+			vdbg ("udsl_decode_rawcell found vcc %p for packet on vpi %d, vci %d", vcc, vpi, vci);
 
 			if (skb->len >= 53) {
 				cell_payload = cell + 5;
@@ -328,7 +330,7 @@
 						tmp = vcc->reasBuffer;
 						vcc->reasBuffer = NULL;
 
-						dbg ("udsl_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", tmp, tmp->len);
+						vdbg ("udsl_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", tmp, tmp->len);
 						return tmp;
 					}
 				}
@@ -352,7 +354,7 @@
 	uint crc = 0xffffffff;
 	uint length, pdu_crc, pdu_length;
 
-	dbg ("udsl_decode_aal5 (0x%p, 0x%p) called", ctx, skb);
+	vdbg ("udsl_decode_aal5 (0x%p, 0x%p) called", ctx, skb);
 
 	if (skb->len && (skb->len % 48))
 		return NULL;
@@ -362,12 +364,11 @@
 	    (skb->tail[-4] << 24) + (skb->tail[-3] << 16) + (skb->tail[-2] << 8) + skb->tail[-1];
 	pdu_length = ((length + 47 + 8) / 48) * 48;
 
-	dbg ("udsl_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", skb->len, length, pdu_crc, pdu_length);
+	vdbg ("udsl_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", skb->len, length, pdu_crc, pdu_length);
 
 	/* is skb long enough ? */
 	if (skb->len < pdu_length) {
-		if (ctx->vcc->stats)
-			atomic_inc (&ctx->vcc->stats->rx_err);
+		atomic_inc (&ctx->vcc->stats->rx_err);
 		return NULL;
 	}
 
@@ -386,8 +387,7 @@
 	/* check crc */
 	if (pdu_crc != crc) {
 		dbg ("udsl_decode_aal5: crc check failed!");
-		if (ctx->vcc->stats)
-			atomic_inc (&ctx->vcc->stats->rx_err);
+		atomic_inc (&ctx->vcc->stats->rx_err);
 		return NULL;
 	}
 
@@ -395,10 +395,9 @@
 	skb_trim (skb, length);
 
 	/* update stats */
-	if (ctx->vcc->stats)
-		atomic_inc (&ctx->vcc->stats->rx);
+	atomic_inc (&ctx->vcc->stats->rx);
 
-	dbg ("udsl_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len);
+	vdbg ("udsl_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len);
 	return skb;
 }
 
@@ -454,7 +453,7 @@
 	unsigned char *target = *target_p;
 	unsigned int nc, ne, i;
 
-	dbg ("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding);
+	vdbg ("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding);
 
 	nc = ctrl->num_cells;
 	ne = min (howmany, ctrl->num_entire);
@@ -521,7 +520,7 @@
 		return;
 	}
 
-	dbg ("udsl_complete_receive entered (urb 0x%p, status %d)", urb, urb->status);
+	vdbg ("udsl_complete_receive entered (urb 0x%p, status %d)", urb, urb->status);
 
 	/* may not be in_interrupt() */
 	spin_lock_irqsave (&instance->completed_receivers_lock, flags);
@@ -534,7 +533,6 @@
 {
 	struct udsl_instance_data *instance = (struct udsl_instance_data *) data;
 	struct udsl_receiver *rcv;
-	unsigned long flags;
 	unsigned char *data_start;
 	struct sk_buff *skb;
 	struct urb *urb;
@@ -542,20 +540,20 @@
 	struct sk_buff *new = NULL, *tmp = NULL;
 	int err;
 
-	dbg ("udsl_process_receive entered");
+	vdbg ("udsl_process_receive entered");
 
-	spin_lock_irqsave (&instance->completed_receivers_lock, flags);
+	spin_lock_irq (&instance->completed_receivers_lock);
 	while (!list_empty (&instance->completed_receivers)) {
 		rcv = list_entry (instance->completed_receivers.next, struct udsl_receiver, list);
 		list_del (&rcv->list);
-		spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
+		spin_unlock_irq (&instance->completed_receivers_lock);
 
 		urb = rcv->urb;
-		dbg ("udsl_process_receive: got packet %p with length %d and status %d", urb, urb->actual_length, urb->status);
+		vdbg ("udsl_process_receive: got packet %p with length %d and status %d", urb, urb->actual_length, urb->status);
 
 		switch (urb->status) {
 		case 0:
-			dbg ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p", rcv, urb, rcv->skb);
+			vdbg ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p", rcv, urb, rcv->skb);
 
 			/* update the skb structure */
 			skb = rcv->skb;
@@ -563,18 +561,18 @@
 			skb_put (skb, urb->actual_length);
 			data_start = skb->data;
 
-			dbg ("skb->len = %d", skb->len);
+			vdbg ("skb->len = %d", skb->len);
 			PACKETDEBUG (skb->data, skb->len);
 
 			while ((new = udsl_decode_rawcell (instance, skb, &atmsar_vcc))) {
-				dbg ("(after cell processing)skb->len = %d", new->len);
+				vdbg ("(after cell processing)skb->len = %d", new->len);
 
 				tmp = new;
 				new = udsl_decode_aal5 (atmsar_vcc, new);
 
 				/* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */
 				if (new) {
-					dbg ("(after aal5 decap) skb->len = %d", new->len);
+					vdbg ("(after aal5 decap) skb->len = %d", new->len);
 					if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) {
 						PACKETDEBUG (new->data, new->len);
 						atmsar_vcc->vcc->push (atmsar_vcc->vcc, new);
@@ -605,31 +603,30 @@
 			dbg ("udsl_process_receive: submission failed (%d)", err);
 			/* fall through */
 		default: /* error or urb unlinked */
-			dbg ("udsl_process_receive: adding to spare_receivers");
-			spin_lock_irqsave (&instance->spare_receivers_lock, flags);
+			vdbg ("udsl_process_receive: adding to spare_receivers");
+			spin_lock_irq (&instance->spare_receivers_lock);
 			list_add (&rcv->list, &instance->spare_receivers);
-			spin_unlock_irqrestore (&instance->spare_receivers_lock, flags);
+			spin_unlock_irq (&instance->spare_receivers_lock);
 			break;
 		} /* switch */
 
-		spin_lock_irqsave (&instance->completed_receivers_lock, flags);
+		spin_lock_irq (&instance->completed_receivers_lock);
 	} /* while */
-	spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
-	dbg ("udsl_process_receive successful");
+	spin_unlock_irq (&instance->completed_receivers_lock);
+	vdbg ("udsl_process_receive successful");
 }
 
 static void udsl_fire_receivers (struct udsl_instance_data *instance)
 {
 	struct list_head receivers, *pos, *n;
-	unsigned long flags;
 
 	INIT_LIST_HEAD (&receivers);
 
 	down (&instance->serialize);
 
-	spin_lock_irqsave (&instance->spare_receivers_lock, flags);
+	spin_lock_irq (&instance->spare_receivers_lock);
 	list_splice_init (&instance->spare_receivers, &receivers);
-	spin_unlock_irqrestore (&instance->spare_receivers_lock, flags);
+	spin_unlock_irq (&instance->spare_receivers_lock);
 
 	list_for_each_safe (pos, n, &receivers) {
 		struct udsl_receiver *rcv = list_entry (pos, struct udsl_receiver, list);
@@ -646,9 +643,9 @@
 
 		if (usb_submit_urb (rcv->urb, GFP_KERNEL) < 0) {
 			dbg ("udsl_fire_receivers: submit failed!");
-			spin_lock_irqsave (&instance->spare_receivers_lock, flags);
+			spin_lock_irq (&instance->spare_receivers_lock);
 			list_move (pos, &instance->spare_receivers);
-			spin_unlock_irqrestore (&instance->spare_receivers_lock, flags);
+			spin_unlock_irq (&instance->spare_receivers_lock);
 		}
 	}
 
@@ -671,7 +668,7 @@
 		return;
 	}
 
-	dbg ("udsl_complete_send entered (urb 0x%p, status %d)", urb, urb->status);
+	vdbg ("udsl_complete_send: urb 0x%p, status %d, snd 0x%p, buf 0x%p", urb, urb->status, snd, snd->buffer);
 
 	/* may not be in_interrupt() */
 	spin_lock_irqsave (&instance->send_lock, flags);
@@ -685,30 +682,25 @@
 {
 	struct udsl_send_buffer *buf;
 	int err;
-	unsigned long flags;
 	struct udsl_instance_data *instance = (struct udsl_instance_data *) data;
 	unsigned int num_written;
 	struct sk_buff *skb;
 	struct udsl_sender *snd;
 
-	dbg ("udsl_process_send entered");
-
 made_progress:
-	spin_lock_irqsave (&instance->send_lock, flags);
+	spin_lock_irq (&instance->send_lock);
 	while (!list_empty (&instance->spare_senders)) {
 		if (!list_empty (&instance->filled_buffers)) {
 			buf = list_entry (instance->filled_buffers.next, struct udsl_send_buffer, list);
 			list_del (&buf->list);
-			dbg ("sending filled buffer (0x%p)", buf);
 		} else if ((buf = instance->current_buffer)) {
 			instance->current_buffer = NULL;
-			dbg ("sending current buffer (0x%p)", buf);
 		} else /* all buffers empty */
 			break;
 
 		snd = list_entry (instance->spare_senders.next, struct udsl_sender, list);
 		list_del (&snd->list);
-		spin_unlock_irqrestore (&instance->send_lock, flags);
+		spin_unlock_irq (&instance->send_lock);
 
 		snd->buffer = buf;
 	        usb_fill_bulk_urb (snd->urb,
@@ -719,39 +711,37 @@
 				   udsl_complete_send,
 				   snd);
 
-		dbg ("submitting urb 0x%p, contains %d cells", snd->urb, UDSL_SND_BUFFER_SIZE - buf->free_cells);
+		vdbg ("udsl_process_send: submitting urb 0x%p (%d cells), snd 0x%p, buf 0x%p", snd->urb, UDSL_SND_BUF_SIZE - buf->free_cells, snd, buf);
 
 		if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) {
-			dbg ("submission failed (%d)!", err);
-			spin_lock_irqsave (&instance->send_lock, flags);
+			dbg ("udsl_process_send: urb submission failed (%d)!", err);
+			spin_lock_irq (&instance->send_lock);
 			list_add (&snd->list, &instance->spare_senders);
-			spin_unlock_irqrestore (&instance->send_lock, flags);
+			spin_unlock_irq (&instance->send_lock);
 			list_add (&buf->list, &instance->filled_buffers);
 			return;
 		}
 
-		spin_lock_irqsave (&instance->send_lock, flags);
+		spin_lock_irq (&instance->send_lock);
 	} /* while */
-	spin_unlock_irqrestore (&instance->send_lock, flags);
+	spin_unlock_irq (&instance->send_lock);
 
 	if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) {
-		dbg ("done - no more skbs");
-		return;
+		return; /* done - no more skbs */
 	}
 
 	skb = instance->current_skb;
 
 	if (!(buf = instance->current_buffer)) {
-		spin_lock_irqsave (&instance->send_lock, flags);
+		spin_lock_irq (&instance->send_lock);
 		if (list_empty (&instance->spare_buffers)) {
 			instance->current_buffer = NULL;
-			spin_unlock_irqrestore (&instance->send_lock, flags);
-			dbg ("done - no more buffers");
-			return;
+			spin_unlock_irq (&instance->send_lock);
+			return; /* done - no more buffers */
 		}
 		buf = list_entry (instance->spare_buffers.next, struct udsl_send_buffer, list);
 		list_del (&buf->list);
-		spin_unlock_irqrestore (&instance->send_lock, flags);
+		spin_unlock_irq (&instance->send_lock);
 
 		buf->free_start = buf->base;
 		buf->free_cells = UDSL_SND_BUFFER_SIZE;
@@ -761,28 +751,25 @@
 
 	num_written = udsl_write_cells (buf->free_cells, skb, &buf->free_start);
 
-	dbg ("wrote %u cells from skb 0x%p to buffer 0x%p", num_written, skb, buf);
+	vdbg ("udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p", num_written, skb, buf);
 
 	if (!(buf->free_cells -= num_written)) {
 		list_add_tail (&buf->list, &instance->filled_buffers);
 		instance->current_buffer = NULL;
-		dbg ("queued filled buffer");
 	}
 
-	dbg ("buffer contains %d cells, %d left", UDSL_SND_BUFFER_SIZE - buf->free_cells, buf->free_cells);
+	vdbg ("udsl_process_send: buffer contains %d cells, %d left", UDSL_SND_BUF_SIZE - buf->free_cells, buf->free_cells);
 
 	if (!UDSL_SKB (skb)->num_cells) {
 		struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc;
 
-		dbg ("discarding empty skb");
 		if (vcc->pop)
 			vcc->pop (vcc, skb);
 		else
 			kfree_skb (skb);
 		instance->current_skb = NULL;
 
-		if (vcc->stats)
-			atomic_inc (&vcc->stats->tx);
+		atomic_inc (&vcc->stats->tx);
 	}
 
 	goto made_progress;
@@ -790,25 +777,24 @@
 
 static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vcc *vcc)
 {
-	unsigned long flags;
 	struct sk_buff *skb, *n;
 
 	dbg ("udsl_cancel_send entered");
-	spin_lock_irqsave (&instance->sndqueue.lock, flags);
+	spin_lock_irq (&instance->sndqueue.lock);
 	for (skb = instance->sndqueue.next, n = skb->next; skb != (struct sk_buff *)&instance->sndqueue; skb = n, n = skb->next)
 		if (UDSL_SKB (skb)->atm_data.vcc == vcc) {
-			dbg ("popping skb 0x%p", skb);
+			dbg ("udsl_cancel_send: popping skb 0x%p", skb);
 			__skb_unlink (skb, &instance->sndqueue);
 			if (vcc->pop)
 				vcc->pop (vcc, skb);
 			else
 				kfree_skb (skb);
 		}
-	spin_unlock_irqrestore (&instance->sndqueue.lock, flags);
+	spin_unlock_irq (&instance->sndqueue.lock);
 
 	tasklet_disable (&instance->send_tasklet);
 	if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) {
-		dbg ("popping current skb (0x%p)", skb);
+		dbg ("udsl_cancel_send: popping current skb (0x%p)", skb);
 		instance->current_skb = NULL;
 		if (vcc->pop)
 			vcc->pop (vcc, skb);
@@ -823,23 +809,20 @@
 {
 	struct udsl_instance_data *instance = vcc->dev->dev_data;
 
-	dbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);
+	vdbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);
 
 	if (!instance || !instance->usb_dev) {
-		dbg ("NULL data!");
+		dbg ("udsl_atm_send: NULL data!");
 		return -ENODEV;
 	}
 
-	if (!instance->firmware_loaded)
-		return -EAGAIN;
-
 	if (vcc->qos.aal != ATM_AAL5) {
-		dbg ("unsupported ATM type %d!", vcc->qos.aal);
+		dbg ("udsl_atm_send: unsupported ATM type %d!", vcc->qos.aal);
 		return -EINVAL;
 	}
 
 	if (skb->len > ATM_MAX_AAL5_PDU) {
-		dbg ("packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU);
+		dbg ("udsl_atm_send: packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU);
 		return -EINVAL;
 	}
 
@@ -868,9 +851,7 @@
 
 	dbg ("udsl_atm_dev_close: queue has %u elements", instance->sndqueue.qlen);
 
-	dbg ("udsl_atm_dev_close: killing tasklet");
 	tasklet_kill (&instance->send_tasklet);
-	dbg ("udsl_atm_dev_close: freeing instance");
 	kfree (instance);
 	dev->dev_data = NULL;
 }
@@ -881,7 +862,7 @@
 	int left = *pos;
 
 	if (!instance) {
-		dbg ("NULL instance!");
+		dbg ("udsl_atm_proc_read: NULL instance!");
 		return -ENODEV;
 	}
 
@@ -933,10 +914,10 @@
 	struct udsl_instance_data *instance = vcc->dev->dev_data;
 	struct udsl_vcc_data *new;
 
-	dbg ("udsl_atm_open called");
+	dbg ("udsl_atm_open: vpi %hd, vci %d", vpi, vci);
 
 	if (!instance || !instance->usb_dev) {
-		dbg ("NULL data!");
+		dbg ("udsl_atm_open: NULL data!");
 		return -ENODEV;
 	}
 
@@ -948,7 +929,7 @@
 		return -EINVAL;
 
 	if (!instance->firmware_loaded) {
-		dbg ("firmware not loaded!");
+		dbg ("udsl_atm_open: firmware not loaded!");
 		return -EAGAIN;
 	}
 
@@ -984,11 +965,9 @@
 
 	up (&instance->serialize);
 
-	dbg ("Allocated new SARLib vcc 0x%p with vpi %d vci %d", new, vpi, vci);
-
 	udsl_fire_receivers (instance);
 
-	dbg ("udsl_atm_open successful");
+	dbg ("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, new->max_pdu);
 
 	return 0;
 }
@@ -1001,11 +980,11 @@
 	dbg ("udsl_atm_close called");
 
 	if (!instance || !vcc_data) {
-		dbg ("NULL data!");
+		dbg ("udsl_atm_close: NULL data!");
 		return;
 	}
 
-	dbg ("Deallocating SARLib vcc 0x%p with vpi %d vci %d", vcc_data, vcc_data->vpi, vcc_data->vci);
+	dbg ("udsl_atm_close: deallocating vcc 0x%p with vpi %d vci %d", vcc_data, vcc_data->vpi, vcc_data->vci);
 
 	udsl_cancel_send (instance, vcc);
 
@@ -1055,7 +1034,7 @@
 		int ret;
 
 		if ((ret = usb_set_interface (instance->usb_dev, 1, 1)) < 0) {
-			dbg ("usb_set_interface returned %d!", ret);
+			dbg ("udsl_set_alternate: usb_set_interface returned %d!", ret);
 			up (&instance->serialize);
 			return ret;
 		}
@@ -1073,7 +1052,7 @@
 	dbg ("udsl_usb_ioctl entered");
 
 	if (!instance) {
-		dbg ("NULL instance!");
+		dbg ("udsl_usb_ioctl: NULL instance!");
 		return -ENODEV;
 	}
 
@@ -1098,19 +1077,19 @@
 	int i, length;
 	char *buf;
 
-	dbg ("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d",
-		dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+	dbg ("udsl_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d",
+	     dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
 
 	if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) ||
 	    (dev->descriptor.idVendor != SPEEDTOUCH_VENDORID) ||
 	    (dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1))
 		return -ENODEV;
 
-	dbg ("Device Accepted");
+	dbg ("udsl_usb_probe: device accepted");
 
 	/* instance init */
 	if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) {
-		dbg ("No memory for Instance data!");
+		dbg ("udsl_usb_probe: no memory for instance data!");
 		return -ENOMEM;
 	}
 
@@ -1144,12 +1123,12 @@
 		struct udsl_receiver *rcv = &(instance->all_receivers[i]);
 
 		if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE))) {
-			dbg ("No memory for skb %d!", i);
+			dbg ("udsl_usb_probe: no memory for skb %d!", i);
 			goto fail;
 		}
 
 		if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) {
-			dbg ("No memory for receive urb %d!", i);
+			dbg ("udsl_usb_probe: no memory for receive urb %d!", i);
 			goto fail;
 		}
 
@@ -1157,7 +1136,7 @@
 
 		list_add (&rcv->list, &instance->spare_receivers);
 
-		dbg ("skb->truesize = %d (asked for %d)", rcv->skb->truesize, UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE);
+		dbg ("udsl_usb_probe: skb->truesize = %d (asked for %d)", rcv->skb->truesize, UDSL_RCV_BUF_SIZE * ATM_CELL_SIZE);
 	}
 
 	/* send init */
@@ -1165,7 +1144,7 @@
 		struct udsl_sender *snd = &(instance->all_senders[i]);
 
 		if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) {
-			dbg ("No memory for send urb %d!", i);
+			dbg ("udsl_usb_probe: no memory for send urb %d!", i);
 			goto fail;
 		}
 
@@ -1178,7 +1157,7 @@
 		struct udsl_send_buffer *buf = &(instance->all_buffers[i]);
 
 		if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) {
-			dbg ("No memory for send buffer %d!", i);
+			dbg ("udsl_usb_probe: no memory for send buffer %d!", i);
 			goto fail;
 		}
 
@@ -1187,7 +1166,7 @@
 
 	/* atm init */
 	if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) {
-		dbg ("failed to register ATM device!");
+		dbg ("udsl_usb_probe: failed to register ATM device!");
 		goto fail;
 	}
 
@@ -1228,6 +1207,7 @@
 
 finish:
 	/* ready for ATM callbacks */
+	wmb ();
 	instance->atm_dev->dev_data = instance;
 
 	usb_set_intfdata (intf, instance);
@@ -1259,16 +1239,15 @@
 {
 	struct udsl_instance_data *instance = usb_get_intfdata (intf);
 	struct list_head *pos;
-	unsigned long flags;
 	unsigned int count = 0;
 	int result, i;
 
-	dbg ("disconnecting");
+	dbg ("udsl_usb_disconnect entered");
 
 	usb_set_intfdata (intf, NULL);
 
 	if (!instance) {
-		dbg ("NULL instance!");
+		dbg ("udsl_usb_disconnect: NULL instance!");
 		return;
 	}
 
@@ -1295,28 +1274,27 @@
 	do {
 		unsigned int completed = 0;
 
-		spin_lock_irqsave (&instance->completed_receivers_lock, flags);
+		spin_lock_irq (&instance->completed_receivers_lock);
 		list_for_each (pos, &instance->completed_receivers)
 			if (++completed > count)
 				panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__);
-		spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
+		spin_unlock_irq (&instance->completed_receivers_lock);
 
 		dbg ("udsl_usb_disconnect: found %u completed receivers", completed);
 
 		if (completed == count)
 			break;
 
-		yield ();
+		set_current_state (TASK_RUNNING);
+		schedule ();
 	} while (1);
 
-	dbg ("udsl_usb_disconnect: flushing");
 	/* no need to take the spinlock */
 	INIT_LIST_HEAD (&instance->completed_receivers);
 
 	tasklet_enable (&instance->receive_tasklet);
 	tasklet_kill (&instance->receive_tasklet);
 
-	dbg ("udsl_usb_disconnect: freeing receivers");
 	for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
 		struct udsl_receiver *rcv = &(instance->all_receivers[i]);
 
@@ -1334,21 +1312,21 @@
 	/* wait for completion handlers to finish */
 	do {
 		count = 0;
-		spin_lock_irqsave (&instance->send_lock, flags);
+		spin_lock (&instance->send_lock);
 		list_for_each (pos, &instance->spare_senders)
 			if (++count > UDSL_NUMBER_SND_URBS)
 				panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__);
-		spin_unlock_irqrestore (&instance->send_lock, flags);
+		spin_unlock (&instance->send_lock);
 
 		dbg ("udsl_usb_disconnect: found %u spare senders", count);
 
 		if (count == UDSL_NUMBER_SND_URBS)
 			break;
 
-		yield ();
+		set_current_state (TASK_RUNNING);
+		schedule ();
 	} while (1);
 
-	dbg ("udsl_usb_disconnect: flushing");
 	/* no need to take the spinlock */
 	INIT_LIST_HEAD (&instance->spare_senders);
 	INIT_LIST_HEAD (&instance->spare_buffers);
@@ -1356,14 +1334,13 @@
 
 	tasklet_enable (&instance->send_tasklet);
 
-	dbg ("udsl_usb_disconnect: freeing senders");
 	for (i = 0; i < UDSL_NUMBER_SND_URBS; i++)
 		usb_free_urb (instance->all_senders[i].urb);
 
-	dbg ("udsl_usb_disconnect: freeing buffers");
 	for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++)
 		kfree (instance->all_buffers[i].base);
 
+	wmb ();
 	instance->usb_dev = NULL;
 
 	/* atm finalize */
@@ -1391,7 +1368,7 @@
 
 static void __exit udsl_usb_cleanup (void)
 {
-	dbg ("udsl_usb_cleanup");
+	dbg ("udsl_usb_cleanup entered");
 
 	usb_deregister (&udsl_usb_driver);
 }
@@ -1408,7 +1385,7 @@
 **  debug  **
 ************/
 
-#ifdef DEBUG_PACKET
+#ifdef VERBOSE_DEBUG
 static int udsl_print_packet (const unsigned char *data, int len)
 {
 	unsigned char buffer [256];
diff -urN linux-2.5.69-bk14/drivers/usb/misc/usbtest.c linux-2.5.69-bk15/drivers/usb/misc/usbtest.c
--- linux-2.5.69-bk14/drivers/usb/misc/usbtest.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/misc/usbtest.c	2003-05-21 04:47:34.000000000 -0700
@@ -1349,6 +1349,13 @@
 	.alt		= 0,
 };
 
+static struct usbtest_info um_info = {
+	.name		= "user mode test driver",
+	.ep_in		= 7,
+	.ep_out		= 3,
+	.alt		= -1,
+};
+
 #ifdef IBOT2
 /* this is a nice source of high speed bulk data;
  * uses an FX2, with firmware provided in the device
@@ -1414,6 +1421,11 @@
 		.driver_info = (unsigned long) &fw_info,
 		},
 
+	/* so does a user-mode variant */
+	{ USB_DEVICE (0x0525, 0xa4a4),
+		.driver_info = (unsigned long) &um_info,
+		},
+
 #ifdef KEYSPAN_19Qi
 	/* Keyspan 19qi uses an21xx (original EZ-USB) */
 	// this does not coexist with the real Keyspan 19qi driver!
diff -urN linux-2.5.69-bk14/drivers/usb/net/usbnet.c linux-2.5.69-bk15/drivers/usb/net/usbnet.c
--- linux-2.5.69-bk14/drivers/usb/net/usbnet.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/net/usbnet.c	2003-05-21 04:47:34.000000000 -0700
@@ -2597,7 +2597,8 @@
 		return status;
 	}
 	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
-
+	
+	SET_NETDEV_DEV(&dev->net, &dev->udev->dev);
 	register_netdev (&dev->net);
 	devinfo (dev, "register usbnet at usb-%s-%s, %s",
 		xdev->bus->bus_name, xdev->devpath,
diff -urN linux-2.5.69-bk14/drivers/usb/storage/freecom.c linux-2.5.69-bk15/drivers/usb/storage/freecom.c
--- linux-2.5.69-bk14/drivers/usb/storage/freecom.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/storage/freecom.c	2003-05-21 04:47:34.000000000 -0700
@@ -134,7 +134,8 @@
 
 	/* Now transfer all of our blocks. */
 	US_DEBUGP("Start of read\n");
-	result = usb_stor_bulk_transfer_srb(us, ipipe, srb, count);
+	result = usb_stor_bulk_transfer_sg(us, ipipe, srb->request_buffer,
+			count, srb->use_sg, &srb->resid);
 	US_DEBUGP("freecom_readdata done!\n");
 
 	if (result > USB_STOR_XFER_SHORT)
@@ -168,7 +169,8 @@
 
 	/* Now transfer all of our blocks. */
 	US_DEBUGP("Start of write\n");
-	result = usb_stor_bulk_transfer_srb(us, opipe, srb, count);
+	result = usb_stor_bulk_transfer_sg(us, opipe, srb->request_buffer,
+			count, srb->use_sg, &srb->resid);
 
 	US_DEBUGP("freecom_writedata done!\n");
 	if (result > USB_STOR_XFER_SHORT)
diff -urN linux-2.5.69-bk14/drivers/usb/storage/sddr09.c linux-2.5.69-bk15/drivers/usb/storage/sddr09.c
--- linux-2.5.69-bk14/drivers/usb/storage/sddr09.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/storage/sddr09.c	2003-05-21 04:47:34.000000000 -0700
@@ -1562,8 +1562,10 @@
 			  "sending" : "receiving",
 			  srb->request_bufflen);
 
-		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
-							srb->request_bufflen);
+		result = usb_stor_bulk_transfer_sg(us, pipe,
+					srb->request_buffer,
+					srb->request_bufflen,
+					srb->use_sg, &srb->resid);
 
 		return (result == USB_STOR_XFER_GOOD ?
 			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
diff -urN linux-2.5.69-bk14/drivers/usb/storage/transport.c linux-2.5.69-bk15/drivers/usb/storage/transport.c
--- linux-2.5.69-bk14/drivers/usb/storage/transport.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/storage/transport.c	2003-05-21 04:47:34.000000000 -0700
@@ -511,9 +511,8 @@
 	 * short-circuit all other processing
 	 */
 	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("-- transport indicates command was aborted\n");
-		srb->result = DID_ABORT << 16;
-		return;
+		US_DEBUGP("-- command was aborted\n");
+		goto Handle_Abort;
 	}
 
 	/* if there is a transport error, reset and don't auto-sense */
@@ -634,8 +633,7 @@
 
 		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 			US_DEBUGP("-- auto-sense aborted\n");
-			srb->result = DID_ABORT << 16;
-			return;
+			goto Handle_Abort;
 		}
 		if (temp_result != USB_STOR_TRANSPORT_GOOD) {
 			US_DEBUGP("-- auto-sense failure\n");
@@ -688,6 +686,15 @@
 	    (result == USB_STOR_TRANSPORT_GOOD) &&
 	    ((srb->sense_buffer[2] & 0xf) == 0x0))
 		srb->sense_buffer[0] = 0x0;
+	return;
+
+	/* abort processing: the bulk-only transport requires a reset
+	 * following an abort */
+	Handle_Abort:
+	srb->result = DID_ABORT << 16;
+	if (us->protocol == US_PR_BULK) {
+		us->transport_reset(us);
+	}
 }
 
 /* Abort the currently running scsi command or device reset.
@@ -772,8 +779,9 @@
 	if (transfer_length) {
 		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
-		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
-					transfer_length);
+		result = usb_stor_bulk_transfer_sg(us, pipe,
+					srb->request_buffer, transfer_length,
+					srb->use_sg, &srb->resid);
 		US_DEBUGP("CBI data stage result is 0x%x\n", result);
 		if (result == USB_STOR_XFER_ERROR)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -862,8 +870,9 @@
 	if (transfer_length) {
 		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
-		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
-					transfer_length);
+		result = usb_stor_bulk_transfer_sg(us, pipe,
+					srb->request_buffer, transfer_length,
+					srb->use_sg, &srb->resid);
 		US_DEBUGP("CB data stage result is 0x%x\n", result);
 		if (result == USB_STOR_XFER_ERROR)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -944,8 +953,9 @@
 	if (transfer_length) {
 		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
-		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
-					transfer_length);
+		result = usb_stor_bulk_transfer_sg(us, pipe,
+					srb->request_buffer, transfer_length,
+					srb->use_sg, &srb->resid);
 		US_DEBUGP("Bulk data transfer result 0x%x\n", result);
 		if (result == USB_STOR_XFER_ERROR)
 			return USB_STOR_TRANSPORT_ERROR;
diff -urN linux-2.5.69-bk14/drivers/usb/storage/transport.h linux-2.5.69-bk15/drivers/usb/storage/transport.h
--- linux-2.5.69-bk14/drivers/usb/storage/transport.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/storage/transport.h	2003-05-21 04:47:34.000000000 -0700
@@ -178,10 +178,4 @@
 extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
 		void *buf, unsigned int length, int use_sg, int *residual);
 
-static __inline__ int usb_stor_bulk_transfer_srb(struct us_data *us,
-		unsigned int pipe, Scsi_Cmnd *srb, unsigned int length) {
-	return usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer,
-			length, srb->use_sg, &srb->resid);
-}
-
 #endif
diff -urN linux-2.5.69-bk14/drivers/usb/usb-skeleton.c linux-2.5.69-bk15/drivers/usb/usb-skeleton.c
--- linux-2.5.69-bk14/drivers/usb/usb-skeleton.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/drivers/usb/usb-skeleton.c	2003-05-21 04:47:34.000000000 -0700
@@ -126,8 +126,8 @@
 static int skel_open		(struct inode *inode, struct file *file);
 static int skel_release		(struct inode *inode, struct file *file);
 
-static int skel_probe		(struct usb_interface *intf, const struct usb_device_id *id);
-static void skel_disconnect	(struct usb_interface *intf);
+static int skel_probe		(struct usb_interface *interface, const struct usb_device_id *id);
+static void skel_disconnect	(struct usb_interface *interface);
 
 static void skel_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 
@@ -163,7 +163,7 @@
  * usb class driver info in order to get a minor number from the usb core,
  * and to have the device registered with devfs and the driver core
  */
-static struct usb_class_driver skell_class = {
+static struct usb_class_driver skel_class = {
 	.name =		"usb/skel%d",
 	.fops =		&skel_fops,
 	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
@@ -515,7 +515,7 @@
 		return -ENODEV;
 	}
 
-	retval = usb_register_dev (intf, &skel_class);
+	retval = usb_register_dev (interface, &skel_class);
 	if (retval) {
 		/* something prevented us from registering this driver */
 		err ("Not able to get a minor for this device.");
@@ -533,7 +533,7 @@
 	init_MUTEX (&dev->sem);
 	dev->udev = udev;
 	dev->interface = interface;
-	dev->minor = intf->minor;
+	dev->minor = interface->minor;
 
 	/* set up the endpoint information */
 	/* check out the endpoints */
@@ -610,7 +610,7 @@
 	dev = NULL;
 
 exit_minor:
-	usb_deregister_dev (intf, &skel_class);
+	usb_deregister_dev (interface, &skel_class);
 
 exit:
 	if (dev) {
@@ -654,7 +654,7 @@
 	minor = dev->minor;
 
 	/* give back our minor */
-	usb_deregister_dev (intf, &skel_class);
+	usb_deregister_dev (interface, &skel_class);
 
 	/* terminate an ongoing write */
 	if (atomic_read (&dev->write_busy)) {
diff -urN linux-2.5.69-bk14/fs/dcache.c linux-2.5.69-bk15/fs/dcache.c
--- linux-2.5.69-bk14/fs/dcache.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/fs/dcache.c	2003-05-21 04:47:34.000000000 -0700
@@ -1275,7 +1275,7 @@
  * the string " (deleted)" is appended. Note that this is ambiguous. Returns
  * the buffer.
  *
- * "buflen" should be %PAGE_SIZE or more. Caller holds the dcache_lock.
+ * "buflen" should be positive. Caller holds the dcache_lock.
  */
 static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
 			struct dentry *root, struct vfsmount *rootmnt,
@@ -1290,9 +1290,13 @@
 	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
 		buflen -= 10;
 		end -= 10;
+		if (buflen < 0)
+			goto Elong;
 		memcpy(end, " (deleted)", 10);
 	}
 
+	if (buflen < 1)
+		goto Elong;
 	/* Get '/' right */
 	retval = end-1;
 	*retval = '/';
@@ -1315,7 +1319,7 @@
 		namelen = dentry->d_name.len;
 		buflen -= namelen + 1;
 		if (buflen < 0)
-			return ERR_PTR(-ENAMETOOLONG);
+			goto Elong;
 		end -= namelen;
 		memcpy(end, dentry->d_name.name, namelen);
 		*--end = '/';
@@ -1328,12 +1332,13 @@
 global_root:
 	namelen = dentry->d_name.len;
 	buflen -= namelen;
-	if (buflen >= 0) {
-		retval -= namelen-1;	/* hit the slash */
-		memcpy(retval, dentry->d_name.name, namelen);
-	} else
-		retval = ERR_PTR(-ENAMETOOLONG);
+	if (buflen < 0)
+		goto Elong;
+	retval -= namelen-1;	/* hit the slash */
+	memcpy(retval, dentry->d_name.name, namelen);
 	return retval;
+Elong:
+	return ERR_PTR(-ENAMETOOLONG);
 }
 
 /* write full pathname into buffer and return start of pathname */
diff -urN linux-2.5.69-bk14/fs/namespace.c linux-2.5.69-bk15/fs/namespace.c
--- linux-2.5.69-bk14/fs/namespace.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/fs/namespace.c	2003-05-21 04:47:34.000000000 -0700
@@ -211,19 +211,10 @@
 		{ 0, NULL }
 	};
 	struct proc_fs_info *fs_infop;
-	char *path_buf, *path;
-
-	path_buf = (char *) __get_free_page(GFP_KERNEL);
-	if (!path_buf)
-		return -ENOMEM;
-	path = d_path(mnt->mnt_root, mnt, path_buf, PAGE_SIZE);
-	if (IS_ERR(path))
-		path = " (too long)";
 
 	mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
 	seq_putc(m, ' ');
-	mangle(m, path);
-	free_page((unsigned long) path_buf);
+	seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
 	seq_putc(m, ' ');
 	mangle(m, mnt->mnt_sb->s_type->name);
 	seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
diff -urN linux-2.5.69-bk14/fs/nfsd/export.c linux-2.5.69-bk15/fs/nfsd/export.c
--- linux-2.5.69-bk14/fs/nfsd/export.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/fs/nfsd/export.c	2003-05-21 04:47:34.000000000 -0700
@@ -848,12 +848,18 @@
  * export point with fsid==0
  */
 int
-exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp)
+exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
+	       struct cache_req *creq)
 {
 	struct svc_expkey *fsid_key;
 	int rv;
+	u32 fsidv[2];
 
-	fsid_key = exp_get_fsid_key(clp, 0);
+	mk_fsid_v1(fsidv, 0);
+
+	fsid_key = exp_find_key(clp, 1, fsidv, creq);
+	if (IS_ERR(fsid_key) && PTR_ERR(fsid_key) == -EAGAIN)
+		return nfserr_dropit;
 	if (!fsid_key || IS_ERR(fsid_key))
 		return nfserr_perm;
 
diff -urN linux-2.5.69-bk14/fs/nfsd/nfs4proc.c linux-2.5.69-bk15/fs/nfsd/nfs4proc.c
--- linux-2.5.69-bk14/fs/nfsd/nfs4proc.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk15/fs/nfsd/nfs4proc.c	2003-05-21 04:47:34.000000000 -0700
@@ -50,6 +50,7 @@
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
 #include <linux/nfs4.h>
+#include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
@@ -80,14 +81,14 @@
 		 * Note: create modes (UNCHECKED,GUARDED...) are the same
 		 * in NFSv4 as in v3.
 		 */
-		status = nfsd_create_v3(rqstp, current_fh, open->op_name,
-					open->op_namelen, &open->op_iattr,
+		status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
+					open->op_fname.len, &open->op_iattr,
 					&resfh, open->op_createmode,
 					(u32 *)open->op_verf, &open->op_truncate);
 	}
 	else {
 		status = nfsd_lookup(rqstp, current_fh,
-				     open->op_name, open->op_namelen, &resfh);
+				     open->op_fname.data, open->op_fname.len, &resfh);
 		fh_unlock(current_fh);
 	}
 
@@ -107,45 +108,25 @@
 	return status;
 }
 
-static int
-nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
-{
-	struct iattr iattr;
-	int status;
-
-	if (open->op_truncate) {
-		iattr.ia_valid = ATTR_SIZE;
-		iattr.ia_size = 0;
-		status = nfsd_setattr(rqstp, current_fh, &iattr, 0, (time_t)0);
-		if (status)
-			return status;
-	}
-
-	memset(&open->op_stateid, 0xff, sizeof(stateid_t));
-	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
-	return 0;
-}
-
 static inline int
 nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
 	int status;
+	dprintk("NFSD: nfsd4_open filename %.*s\n",open->op_fname.len, open->op_fname.data);
 
 	/* This check required by spec. */
 	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
 		return nfserr_inval;
 
-	/*
-	 * For now, we have no state, so we may as well implement an
-	 * even stronger check...
-	 */
-	if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
-		return nfserr_notsupp;
-
+	/* check seqid for replay. set nfs4_owner */
+	status = nfsd4_process_open1(open);
+	if (status)
+		return status;
 	/*
 	 * This block of code will (1) set CURRENT_FH to the file being opened,
-	 * creating it if necessary, (2) set open->op_cinfo, (3) set open->op_truncate
-	 * if the file is to be truncated after opening, (4) do permission checking.
+	 * creating it if necessary, (2) set open->op_cinfo, 
+	 * (3) set open->op_truncate if the file is to be truncated 
+	 * after opening, (4) do permission checking.
 	 */
 	status = do_open_lookup(rqstp, current_fh, open);
 	if (status)
@@ -159,7 +140,6 @@
 	status = nfsd4_process_open2(rqstp, current_fh, open);
 	if (status)
 		return status;
-
 	/*
 	 * To finish the open response, we just need to set the rflags.
 	 */
@@ -199,7 +179,8 @@
 nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
 {
 	fh_put(current_fh);
-	return exp_pseudoroot(rqstp->rq_client, current_fh);
+	return exp_pseudoroot(rqstp->rq_client, current_fh,
+			      &rqstp->rq_chandle);
 }
 
 static inline int
diff -urN linux-2.5.69-bk14/fs/nfsd/nfs4state.c linux-2.5.69-bk15/fs/nfsd/nfs4state.c
--- linux-2.5.69-bk14/fs/nfsd/nfs4state.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk15/fs/nfsd/nfs4state.c	2003-05-21 04:47:34.000000000 -0700
@@ -42,15 +42,24 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
+#include <linux/mount.h>
 #include <linux/nfs4.h>
-#include <linux/nfsd/xdr4.h>
 #include <linux/nfsd/state.h>
+#include <linux/nfsd/xdr4.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
 /* Globals */
 time_t boot_time;
 static u32 current_clientid = 1;
+static u32 current_ownerid = 0;
+static u32 current_fileid = 0;
+
+/* debug counters */
+u32 list_add_perfile = 0; 
+u32 list_del_perfile = 0;
+u32 add_perclient = 0;
+u32 del_perclient = 0;
 
 /* Locking:
  *
@@ -73,6 +82,14 @@
 	return x;
 }
 
+/* forward declarations */
+static void release_stateowner(struct nfs4_stateowner *sop);
+static void release_stateid(struct nfs4_stateid *stp);
+
+/* 
+ * SETCLIENTID state 
+ */
+
 /* Hash tables for nfs4_clientid state */
 #define CLIENT_HASH_BITS                 4
 #define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
@@ -138,9 +155,15 @@
 static void
 expire_client(struct nfs4_client *clp)
 {
+	struct nfs4_stateowner *sop;
+
 	dprintk("NFSD: expire_client\n");
 	list_del(&clp->cl_idhash);
 	list_del(&clp->cl_strhash);
+	while (!list_empty(&clp->cl_perclient)) {
+		sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
+		release_stateowner(sop);
+	}
 	free_client(clp);
 }
 
@@ -152,6 +175,7 @@
 		goto out;
 	INIT_LIST_HEAD(&clp->cl_idhash);
 	INIT_LIST_HEAD(&clp->cl_strhash);
+	INIT_LIST_HEAD(&clp->cl_perclient);
 out:
 	return clp;
 }
@@ -225,7 +249,7 @@
 
 	if (name.len == 0) 
 		return 0;
-	if (name.len > NFSD4_CLIENT_MAXNAME) {
+	if (name.len > NFS4_OPAQUE_LIMIT) {
 		printk("NFSD: check_name: name too long(%d)!\n", name.len);
 		return 0;
 	}
@@ -590,7 +614,442 @@
 	return status;
 }
 
-void
+/* 
+ * Open owner state (share locks)
+ */
+
+/* hash tables for nfs4_stateowner */
+#define OWNER_HASH_BITS              8
+#define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
+#define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
+
+#define ownerstr_hashval(clientid, ownername) \
+        (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
+
+static struct list_head	ownerstr_hashtbl[OWNER_HASH_SIZE];
+
+/* hash table for nfs4_file */
+#define FILE_HASH_BITS                   8
+#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
+#define FILE_HASH_MASK                  (FILE_HASH_SIZE - 1)
+
+#define file_hashval(x) \
+        ((unsigned int)((x)->dev + (x)->ino + (x)->generation) & FILE_HASH_MASK)
+
+static struct list_head file_hashtbl[FILE_HASH_SIZE];
+
+/* OPEN Share state helper functions */
+static inline struct nfs4_file *
+alloc_init_file(unsigned int hashval, nfs4_ino_desc_t *ino) {
+	struct nfs4_file *fp;
+	if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
+		INIT_LIST_HEAD(&fp->fi_hash);
+		INIT_LIST_HEAD(&fp->fi_perfile);
+		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+		memcpy(&fp->fi_ino, ino, sizeof(nfs4_ino_desc_t));
+		fp->fi_id = current_fileid++;
+		return fp;
+	}
+	return (struct nfs4_file *)NULL;
+}
+
+static void
+release_all_files(void)
+{
+	int i;
+	struct nfs4_file *fp;
+
+	for (i=0;i<FILE_HASH_SIZE;i++) {
+		while (!list_empty(&file_hashtbl[i])) {
+			fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
+			/* this should never be more than once... */
+			if(!list_empty(&fp->fi_perfile)) {
+				printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
+			}
+			list_del_init(&fp->fi_hash);
+			kfree(fp);
+		}
+	}
+}
+
+static inline struct nfs4_stateowner *
+alloc_stateowner(struct xdr_netobj *owner)
+{
+	struct nfs4_stateowner *sop;
+
+	if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
+		if((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
+			memcpy(sop->so_owner.data, owner->data, owner->len);
+			sop->so_owner.len = owner->len;
+			return sop;
+		} 
+		kfree(sop);
+	}
+	return (struct nfs4_stateowner *)NULL;
+}
+
+/* should use a slab cache */
+static void
+free_stateowner(struct nfs4_stateowner *sop) {
+	if(sop) {
+		kfree(sop->so_owner.data);
+		kfree(sop);
+		sop = NULL;
+	}
+}
+
+static struct nfs4_stateowner *
+alloc_init_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
+	struct nfs4_stateowner *sop;
+
+	if (!(sop = alloc_stateowner(&open->op_owner)))
+		return (struct nfs4_stateowner *)NULL;
+	INIT_LIST_HEAD(&sop->so_strhash);
+	INIT_LIST_HEAD(&sop->so_perclient);
+	INIT_LIST_HEAD(&sop->so_peropenstate);
+	list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
+	list_add(&sop->so_perclient, &clp->cl_perclient);
+	add_perclient++;
+	sop->so_id = current_ownerid++;
+	sop->so_client = clp;
+	sop->so_seqid = open->op_seqid;
+	/* until open_confirm is coded, pretend it happened! */
+	sop->so_confirmed = 1;
+	return sop;
+}
+
+static void
+release_stateowner(struct nfs4_stateowner *sop)
+{
+	struct nfs4_stateid *stp;
+
+	list_del_init(&sop->so_strhash);
+	list_del_init(&sop->so_perclient);
+	del_perclient++;
+	while (!list_empty(&sop->so_peropenstate)) {
+		stp = list_entry(sop->so_peropenstate.next, 
+			struct nfs4_stateid, st_peropenstate);
+		release_stateid(stp);
+	}
+	free_stateowner(sop);
+}
+
+static inline void
+init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
+
+	INIT_LIST_HEAD(&stp->st_peropenstate);
+	INIT_LIST_HEAD(&stp->st_perfile);
+	list_add(&stp->st_peropenstate, &sop->so_peropenstate);
+	list_add_perfile++;
+	list_add(&stp->st_perfile, &fp->fi_perfile);
+	stp->st_stateowner = sop;
+	stp->st_file = fp;
+	stp->st_stateid.si_boot = boot_time;
+	stp->st_stateid.si_stateownerid = sop->so_id;
+	stp->st_stateid.si_fileid = fp->fi_id;
+	stp->st_stateid.si_generation = 0;
+	stp->st_share_access = open->op_share_access;
+	stp->st_share_deny = open->op_share_deny;
+}
+
+static void
+release_stateid(struct nfs4_stateid *stp) {
+
+	list_del_perfile++;
+	list_del_init(&stp->st_perfile);
+	list_del_init(&stp->st_peropenstate);
+	if(stp->st_vfs_set) {
+		nfsd_close(&stp->st_vfs_file);
+		dput(stp->st_vfs_file.f_dentry);
+		mntput(stp->st_vfs_file.f_vfsmnt);
+	}
+	/* should use a slab cache */
+	kfree(stp);
+	stp = NULL;
+}
+
+static int
+cmp_owner_str(struct nfs4_stateowner *sop, struct nfsd4_open *open) {
+	return ((sop->so_owner.len == open->op_owner.len) && 
+	 !memcmp(sop->so_owner.data, open->op_owner.data, sop->so_owner.len) && 
+	  (sop->so_client->cl_clientid.cl_id == open->op_clientid.cl_id));
+}
+
+/* search ownerstr_hashtbl[] for owner */
+static int
+find_stateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nfs4_stateowner **op) {
+	struct list_head *pos, *next;
+	struct nfs4_stateowner *local = NULL;
+
+	list_for_each_safe(pos, next, &ownerstr_hashtbl[hashval]) {
+		local = list_entry(pos, struct nfs4_stateowner, so_strhash);
+		if(!cmp_owner_str(local, open)) 
+			continue;
+		*op = local;
+		return(1);
+	}
+	return 0;
+}
+
+/* see if clientid is in confirmed hash table */
+static int
+verify_clientid(struct nfs4_client **client, clientid_t *clid) {
+
+	struct list_head *pos, *next;
+	struct nfs4_client *clp;
+	unsigned int idhashval = clientid_hashval(clid->cl_id);
+
+	list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
+		clp = list_entry(pos, struct nfs4_client, cl_idhash);
+		if (!cmp_clid(&clp->cl_clientid, clid))
+			continue;
+		*client = clp;
+		return 1;
+	}
+	*client = NULL;
+	return 0;
+}
+
+/* search file_hashtbl[] for file */
+static int
+find_file(unsigned int hashval, nfs4_ino_desc_t *ino, struct nfs4_file **fp) {
+	struct list_head *pos, *next;
+	struct nfs4_file *local = NULL;
+
+	list_for_each_safe(pos, next, &file_hashtbl[hashval]) {
+		local = list_entry(pos, struct nfs4_file, fi_hash);
+		if(!memcmp(&local->fi_ino, ino, sizeof(nfs4_ino_desc_t))) {
+			*fp = local;
+			return(1);
+		}
+	}
+	return 0;
+}
+
+static int
+test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
+	if ((stp->st_share_access & open->op_share_deny) ||
+	    (stp->st_share_deny & open->op_share_access)) {
+		return 0;
+	}
+	return 1;
+}
+
+static inline void
+nfs4_init_ino(nfs4_ino_desc_t *ino, struct svc_fh *fhp)
+{
+	struct inode *inode;
+	if (!fhp->fh_dentry)
+		BUG();
+	inode = fhp->fh_dentry->d_inode;
+	if (!inode)
+		BUG();
+	ino->dev = inode->i_sb->s_dev;
+	ino->ino = inode->i_ino;
+	ino->generation = inode->i_generation;
+}
+
+static inline int
+nfs4_file_upgrade(struct file *filp, unsigned int share_access)
+{
+int status;
+
+	if (share_access & NFS4_SHARE_ACCESS_WRITE) {
+		status = get_write_access(filp->f_dentry->d_inode);
+		if (!status)
+			filp->f_mode = FMODE_WRITE;
+		else
+			return nfserrno(status);
+	}
+	return nfs_ok;
+}
+
+
+/*
+ * nfsd4_process_open1()
+ * 	lookup stateowner.
+ * 		found:
+ * 			check confirmed 
+ * 				confirmed:
+ * 					check seqid
+ * 				not confirmed:
+ * 					delete owner
+ * 					create new owner
+ * 		notfound:
+ * 			verify clientid
+ * 			create new owner
+ */
+int
+nfsd4_process_open1(struct nfsd4_open *open)
+{
+	int status;
+	clientid_t *clientid = &open->op_clientid;
+	struct nfs4_client *clp = NULL;
+	unsigned int strhashval;
+	struct nfs4_stateowner *sop = NULL;
+
+	status = nfserr_inval;
+	if (!check_name(open->op_owner))
+		goto out;
+
+	status = nfserr_stale_clientid;
+	if (STALE_CLIENTID(&open->op_clientid))
+		goto out;
+
+	down(&client_sema); /* XXX need finer grained locking */
+	strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
+	if (find_stateowner_str(strhashval, open, &sop)) {
+		open->op_stateowner = sop;
+		if (open->op_seqid == sop->so_seqid){
+			/* XXX retplay: for now, return bad seqid */
+			status = nfserr_bad_seqid;
+			goto out;
+		}
+		if (sop->so_confirmed) {
+			if (open->op_seqid == sop->so_seqid + 1) { 
+				status = nfs_ok;
+				goto renew;
+			} 
+			status = nfserr_bad_seqid;
+			goto out;
+		}
+		/* If we get here, we received and OPEN for an unconfirmed
+		 * nfs4_stateowner. If seqid's are the same then this 
+		 * is a replay.
+		 * If the sequid's are different, then purge the 
+		 * existing nfs4_stateowner, and instantiate a new one.
+		 */
+		clp = sop->so_client;
+		release_stateowner(sop);
+		goto instantiate_new_owner;
+	} 
+	/* nfs4_stateowner not found. 
+	* verify clientid and instantiate new nfs4_stateowner
+	* if verify fails this is presumably the result of the 
+	* client's lease expiring.
+	*
+	* XXX compare clp->cl_addr with rqstp addr? 
+	*/
+	status = nfserr_expired;
+	if (!verify_clientid(&clp, clientid))
+		goto out;
+instantiate_new_owner:
+	status = nfserr_resource;
+	if (!(sop = alloc_init_stateowner(strhashval, clp, open))) 
+		goto out;
+	open->op_stateowner = sop;
+	status = nfs_ok;
+renew:
+	/* XXX implement LRU and state recovery thread 
+	 * renew will place nfs4_client at end of LRU 
+	 */
+out:
+	up(&client_sema); /*XXX need finer grained locking */
+	return status;
+}
+
+int
+nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+{
+	struct iattr iattr;
+	struct nfs4_stateowner *sop = open->op_stateowner;
+	struct nfs4_file *fp;
+	nfs4_ino_desc_t ino;
+	unsigned int fi_hashval;
+	struct list_head *pos, *next;
+	struct nfs4_stateid *stq, *stp = NULL;
+	int status;
+
+
+	status = nfserr_resource;
+	if (!sop)
+		goto out;
+
+	nfs4_init_ino(&ino, current_fh);
+
+	down(&client_sema); /*XXX need finer grained locking */
+	fi_hashval = file_hashval(&ino);
+	if (find_file(fi_hashval, &ino, &fp)) {
+		/* Search for conflicting share reservations */
+		status = nfserr_share_denied;
+		list_for_each_safe(pos, next, &fp->fi_perfile) {
+		stq = list_entry(pos, struct nfs4_stateid, st_perfile);
+			if(stq->st_stateowner == sop) {
+				stp = stq;
+				continue;
+			}
+			if (!test_share(stq,open))	
+				goto out;
+		}
+	} else {
+	/* No nfs4_file found; allocate and init a new one */
+		status = nfserr_resource;
+		if ((fp = alloc_init_file(fi_hashval, &ino)) == NULL)
+			goto out;
+	}
+
+	if (!stp) {
+		int flags = 0;
+
+		status = nfserr_resource;
+		if ((stp = kmalloc(sizeof(struct nfs4_stateid),
+						GFP_KERNEL)) == NULL)
+			goto out;
+
+		if (open->op_share_access && NFS4_SHARE_ACCESS_WRITE)
+			flags = MAY_WRITE;
+		else
+			flags = MAY_READ;
+		if ((status = nfsd_open(rqstp, current_fh,  S_IFREG,
+			                      flags,
+			                      &stp->st_vfs_file)) != 0)
+			goto out_free;
+
+		dget(stp->st_vfs_file.f_dentry);
+		mntget(stp->st_vfs_file.f_vfsmnt);
+
+		init_stateid(stp, fp, sop, open);
+		stp->st_vfs_set = 1;
+	} else {
+		/* This is an upgrade of an existing OPEN. 
+		 * OR the incoming share with the existing 
+		 * nfs4_stateid share */
+		int share_access = open->op_share_access;
+
+		share_access &= ~(stp->st_share_access);
+
+		/* update the struct file */
+		if ((status = nfs4_file_upgrade(&stp->st_vfs_file, share_access)))
+			goto out;
+		stp->st_share_access |= share_access;
+		stp->st_share_deny |= open->op_share_deny;
+		/* bump the stateid */
+		update_stateid(&stp->st_stateid);
+	}
+	dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n\n",
+	            stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
+	            stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
+
+	if (open->op_truncate) {
+		iattr.ia_valid = ATTR_SIZE;
+		iattr.ia_size = 0;
+		status = nfsd_setattr(rqstp, current_fh, &iattr, 0, (time_t)0);
+		if (status)
+			goto out;
+	}
+	memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
+
+	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
+	status = nfs_ok;
+out:
+	up(&client_sema); /*XXX need finer grained locking */
+	return status;
+out_free:
+	kfree(stp);
+	goto out;
+}
+
+void 
 nfs4_state_init(void)
 {
 	struct timespec 	tv;
@@ -602,6 +1061,12 @@
 		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
 	}
+	for (i = 0; i < FILE_HASH_SIZE; i++) {
+		INIT_LIST_HEAD(&file_hashtbl[i]);
+	}
+	for (i = 0; i < OWNER_HASH_SIZE; i++) {
+		INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
+	}
 	init_MUTEX(&client_sema);
 	tv = CURRENT_TIME;
 	boot_time = tv.tv_sec;
@@ -623,6 +1088,11 @@
 			expire_client(clp);
 		}
 	}
+	release_all_files();
+	dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
+			list_add_perfile, list_del_perfile);
+	dprintk("NFSD: add_perclient %d del_perclient %d\n",
+			add_perclient, del_perclient);
 }
 
 void
diff -urN linux-2.5.69-bk14/fs/nfsd/nfs4xdr.c linux-2.5.69-bk15/fs/nfsd/nfs4xdr.c
--- linux-2.5.69-bk14/fs/nfsd/nfs4xdr.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk15/fs/nfsd/nfs4xdr.c	2003-05-21 04:47:34.000000000 -0700
@@ -53,6 +53,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/name_lookup.h>
 #include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
@@ -483,8 +484,8 @@
 
 	READ_BUF(4 + sizeof(stateid_t));
 	READ32(close->cl_seqid);
-	READ32(close->cl_stateid.st_generation);
-	COPYMEM(&close->cl_stateid.st_other, sizeof(stateid_other_t));
+	READ32(close->cl_stateid.si_generation);
+	COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
 
 	DECODE_TAIL;
 }
@@ -595,11 +596,11 @@
 	READ32(open->op_share_access);
 	READ32(open->op_share_deny);
 	COPYMEM(&open->op_clientid, sizeof(clientid_t));
-	READ32(open->op_ownerlen);
+	READ32(open->op_owner.len);
 
 	/* owner, open_flag */
-	READ_BUF(open->op_ownerlen + 4);
-	SAVEMEM(open->op_owner, open->op_ownerlen);
+	READ_BUF(open->op_owner.len + 4);
+	SAVEMEM(open->op_owner.data, open->op_owner.len);
 	READ32(open->op_create);
 	switch (open->op_create) {
 	case NFS4_OPEN_NOCREATE:
@@ -632,10 +633,10 @@
 	case NFS4_OPEN_CLAIM_NULL:
 	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
 		READ_BUF(4);
-		READ32(open->op_namelen);
-		READ_BUF(open->op_namelen);
-		SAVEMEM(open->op_name, open->op_namelen);
-		if ((status = check_filename(open->op_name, open->op_namelen, nfserr_inval)))
+		READ32(open->op_fname.len);
+		READ_BUF(open->op_fname.len);
+		SAVEMEM(open->op_fname.data, open->op_fname.len);
+		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
 			return status;
 		break;
 	case NFS4_OPEN_CLAIM_PREVIOUS:
@@ -645,10 +646,10 @@
 	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
 		READ_BUF(sizeof(delegation_stateid_t) + 4);
 		COPYMEM(&open->op_delegate_stateid, sizeof(delegation_stateid_t));
-		READ32(open->op_namelen);
-		READ_BUF(open->op_namelen);
-		SAVEMEM(open->op_name, open->op_namelen);
-		if ((status = check_filename(open->op_name, open->op_namelen, nfserr_inval)))
+		READ32(open->op_fname.len);
+		READ_BUF(open->op_fname.len);
+		SAVEMEM(open->op_fname.data, open->op_fname.len);
+		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
 			return status;
 		break;
 	default:
@@ -679,8 +680,8 @@
 	DECODE_HEAD;
 
 	READ_BUF(sizeof(stateid_t) + 12);
-	READ32(read->rd_stateid.st_generation);
-	COPYMEM(&read->rd_stateid.st_other, sizeof(stateid_other_t));
+	READ32(read->rd_stateid.si_generation);
+	COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t));
 	READ64(read->rd_offset);
 	READ32(read->rd_length);
 
@@ -755,8 +756,8 @@
 	DECODE_HEAD;
 
 	READ_BUF(sizeof(stateid_t));
-	READ32(setattr->sa_stateid.st_generation);
-	COPYMEM(&setattr->sa_stateid.st_other, sizeof(stateid_other_t));
+	READ32(setattr->sa_stateid.si_generation);
+	COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
 	if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr)))
 		goto out;
 
@@ -825,8 +826,8 @@
 	DECODE_HEAD;
 
 	READ_BUF(sizeof(stateid_t) + 16);
-	READ32(write->wr_stateid.st_generation);
-	COPYMEM(&write->wr_stateid.st_other, sizeof(stateid_other_t));
+	READ32(write->wr_stateid.si_generation);
+	COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
 	READ64(write->wr_offset);
 	READ32(write->wr_stable_how);
 	if (write->wr_stable_how > 2)
@@ -1543,8 +1544,8 @@
 
 	if (!nfserr) {
 		RESERVE_SPACE(sizeof(stateid_t));
-		WRITE32(close->cl_stateid.st_generation);
-		WRITEMEM(&close->cl_stateid.st_other, sizeof(stateid_other_t));
+		WRITE32(close->cl_stateid.si_generation);
+		WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
 		ADJUST_ARGS();
 	}
 }
@@ -1632,8 +1633,8 @@
 		return;
 
 	RESERVE_SPACE(36 + sizeof(stateid_t));
-	WRITE32(open->op_stateid.st_generation);
-	WRITEMEM(&open->op_stateid.st_other, sizeof(stateid_other_t));
+	WRITE32(open->op_stateid.si_generation);
+	WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
 	WRITECINFO(open->op_cinfo);
 	WRITE32(open->op_rflags);
 	WRITE32(2);
diff -urN linux-2.5.69-bk14/fs/nfsd/nfsctl.c linux-2.5.69-bk15/fs/nfsd/nfsctl.c
--- linux-2.5.69-bk14/fs/nfsd/nfsctl.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk15/fs/nfsd/nfsctl.c	2003-05-21 04:47:34.000000000 -0700
@@ -472,7 +472,6 @@
 	remove_proc_entry("fs/nfs", NULL);
 	nfsd_stat_shutdown();
 	nfsd_lockd_shutdown();
-	nfs4_state_shutdown();
 	unregister_filesystem(&nfsd_fs_type);
 }
 
diff -urN linux-2.5.69-bk14/fs/nfsd/nfssvc.c linux-2.5.69-bk15/fs/nfsd/nfssvc.c
--- linux-2.5.69-bk14/fs/nfsd/nfssvc.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/fs/nfsd/nfssvc.c	2003-05-21 04:47:34.000000000 -0700
@@ -132,6 +132,7 @@
 	if (none_left) {
 		nfsd_serv = NULL;
 		nfsd_racache_shutdown();
+		nfs4_state_shutdown();
 	}
  out:
 	unlock_kernel();
@@ -247,6 +248,7 @@
 		}
 		nfsd_serv = NULL;
 	        nfsd_racache_shutdown();	/* release read-ahead cache */
+		nfs4_state_shutdown();
 	}
 	list_del(&me.list);
 	nfsdstats.th_cnt --;
diff -urN linux-2.5.69-bk14/fs/open.c linux-2.5.69-bk15/fs/open.c
--- linux-2.5.69-bk14/fs/open.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/fs/open.c	2003-05-21 04:47:34.000000000 -0700
@@ -671,8 +671,8 @@
 	if (f->f_flags & O_DIRECT) {
 		if (!inode->i_mapping || !inode->i_mapping->a_ops ||
 			!inode->i_mapping->a_ops->direct_IO) {
-				error = -EINVAL;
-				goto cleanup_all;
+				fput(f);
+				f = ERR_PTR(-EINVAL);
 		}
 	}
 
diff -urN linux-2.5.69-bk14/fs/proc/base.c linux-2.5.69-bk15/fs/proc/base.c
--- linux-2.5.69-bk14/fs/proc/base.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/fs/proc/base.c	2003-05-21 04:47:34.000000000 -0700
@@ -322,21 +322,23 @@
 	return proc_check_root(inode);
 }
 
-extern ssize_t proc_pid_read_maps(struct task_struct *, struct file *,
-				  char *, size_t, loff_t *);
-static ssize_t pid_maps_read(struct file * file, char * buf,
-			      size_t count, loff_t *ppos)
+extern struct seq_operations proc_pid_maps_op;
+static int maps_open(struct inode *inode, struct file *file)
 {
-	struct inode * inode = file->f_dentry->d_inode;
 	struct task_struct *task = proc_task(inode);
-	ssize_t res;
-
-	res = proc_pid_read_maps(task, file, buf, count, ppos);
-	return res;
+	int ret = seq_open(file, &proc_pid_maps_op);
+	if (!ret) {
+		struct seq_file *m = file->private_data;
+		m->private = task;
+	}
+	return ret;
 }
 
 static struct file_operations proc_maps_operations = {
-	.read		= pid_maps_read,
+	.open		= maps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
 };
 
 extern struct seq_operations mounts_op;
diff -urN linux-2.5.69-bk14/fs/proc/task_mmu.c linux-2.5.69-bk15/fs/proc/task_mmu.c
--- linux-2.5.69-bk14/fs/proc/task_mmu.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/fs/proc/task_mmu.c	2003-05-21 04:47:34.000000000 -0700
@@ -1,6 +1,6 @@
-
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 
 char *task_mem(struct mm_struct *mm, char *buffer)
@@ -75,167 +75,86 @@
 	return size;
 }
 
-/*
- * The way we support synthetic files > 4K
- * - without storing their contents in some buffer and
- * - without walking through the entire synthetic file until we reach the
- *   position of the requested data
- * is to cleverly encode the current position in the file's f_pos field.
- * There is no requirement that a read() call which returns `count' bytes
- * of data increases f_pos by exactly `count'.
- *
- * This idea is Linus' one. Bruno implemented it.
- */
-
-/*
- * For the /proc/<pid>/maps file, we use fixed length records, each containing
- * a single line.
- *
- * f_pos = (number of the vma in the task->mm->mmap list) * PAGE_SIZE
- *         + (index into the line)
- */
-/* for systems with sizeof(void*) == 4: */
-#define MAPS_LINE_FORMAT4	  "%08lx-%08lx %s %08lx %02x:%02x %lu"
-#define MAPS_LINE_MAX4	49 /* sum of 8  1  8  1 4 1 8 1 5 1 10 1 */
-
-/* for systems with sizeof(void*) == 8: */
-#define MAPS_LINE_FORMAT8	  "%016lx-%016lx %s %016lx %02x:%02x %lu"
-#define MAPS_LINE_MAX8	73 /* sum of 16  1  16  1 4 1 16 1 5 1 10 1 */
-
-#define MAPS_LINE_FORMAT	(sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8)
-#define MAPS_LINE_MAX	(sizeof(void*) == 4 ?  MAPS_LINE_MAX4 :  MAPS_LINE_MAX8)
-
-static int proc_pid_maps_get_line (char *buf, struct vm_area_struct *map)
-{
-	/* produce the next line */
-	char *line;
-	char str[5];
-	int flags;
-	dev_t dev;
-	unsigned long ino;
+static int show_map(struct seq_file *m, void *v)
+{
+	struct vm_area_struct *map = v;
+	struct file *file = map->vm_file;
+	int flags = map->vm_flags;
+	unsigned long ino = 0;
+	dev_t dev = 0;
 	int len;
 
-	flags = map->vm_flags;
-
-	str[0] = flags & VM_READ ? 'r' : '-';
-	str[1] = flags & VM_WRITE ? 'w' : '-';
-	str[2] = flags & VM_EXEC ? 'x' : '-';
-	str[3] = flags & VM_MAYSHARE ? 's' : 'p';
-	str[4] = 0;
-
-	dev = 0;
-	ino = 0;
-	if (map->vm_file != NULL) {
+	if (file) {
 		struct inode *inode = map->vm_file->f_dentry->d_inode;
 		dev = inode->i_sb->s_dev;
 		ino = inode->i_ino;
-		line = d_path(map->vm_file->f_dentry,
-			      map->vm_file->f_vfsmnt,
-			      buf, PAGE_SIZE);
-		buf[PAGE_SIZE-1] = '\n';
-		line -= MAPS_LINE_MAX;
-		if(line < buf)
-			line = buf;
-	} else
-		line = buf;
-
-	len = sprintf(line,
-		      MAPS_LINE_FORMAT,
-		      map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
-		      MAJOR(dev), MINOR(dev), ino);
-
-	if(map->vm_file) {
-		int i;
-		for(i = len; i < MAPS_LINE_MAX; i++)
-			line[i] = ' ';
-		len = buf + PAGE_SIZE - line;
-		memmove(buf, line, len);
-	} else
-		line[len++] = '\n';
-	return len;
+	}
+
+	seq_printf(m, "%0*lx-%0*lx %c%c%c%c %0*lx %02x:%02x %lu %n",
+			2*sizeof(void*), map->vm_start,
+			2*sizeof(void*), map->vm_end,
+			flags & VM_READ ? 'r' : '-',
+			flags & VM_WRITE ? 'w' : '-',
+			flags & VM_EXEC ? 'x' : '-',
+			flags & VM_MAYSHARE ? 's' : 'p',
+			2*sizeof(void*), map->vm_pgoff << PAGE_SHIFT,
+			MAJOR(dev), MINOR(dev), ino, &len);
+
+	if (map->vm_file) {
+		len = 25 + sizeof(void*) * 6 - len;
+		if (len < 1)
+			len = 1;
+		seq_printf(m, "%*c", len, ' ');
+		seq_path(m, file->f_vfsmnt, file->f_dentry, " \t\n\\");
+	}
+	seq_putc(m, '\n');
+	return 0;
 }
 
-ssize_t proc_pid_read_maps(struct task_struct *task, struct file *file,
-			   char *buf, size_t count, loff_t *ppos)
+static void *m_start(struct seq_file *m, loff_t *pos)
 {
-	struct mm_struct *mm;
+	struct task_struct *task = m->private;
+	struct mm_struct *mm = get_task_mm(task);
 	struct vm_area_struct * map;
-	char *tmp, *kbuf;
-	long retval;
-	int off, lineno, loff;
-
-	/* reject calls with out of range parameters immediately */
-	retval = 0;
-	if (*ppos > LONG_MAX)
-		goto out;
-	if (count == 0)
-		goto out;
-	off = (long)*ppos;
-	/*
-	 * We might sleep getting the page, so get it first.
-	 */
-	retval = -ENOMEM;
-	kbuf = (char*)__get_free_page(GFP_KERNEL);
-	if (!kbuf)
-		goto out;
-
-	tmp = (char*)__get_free_page(GFP_KERNEL);
-	if (!tmp)
-		goto out_free1;
-
-	mm = get_task_mm(task);
- 
-	retval = 0;
+	loff_t l = *pos;
+
 	if (!mm)
-		goto out_free2;
+		return NULL;
 
 	down_read(&mm->mmap_sem);
 	map = mm->mmap;
-	lineno = 0;
-	loff = 0;
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
-	while (map) {
-		int len;
-		if (off > PAGE_SIZE) {
-			off -= PAGE_SIZE;
-			goto next;
-		}
-		len = proc_pid_maps_get_line(tmp, map);
-		len -= off;
-		if (len > 0) {
-			if (retval+len > count) {
-				/* only partial line transfer possible */
-				len = count - retval;
-				/* save the offset where the next read
-				 * must start */
-				loff = len+off;
-			}
-			memcpy(kbuf+retval, tmp+off, len);
-			retval += len;
-		}
-		off = 0;
-next:
-		if (!loff)
-			lineno++;
-		if (retval >= count)
-			break;
-		if (loff) BUG();
+	while (l-- && map)
 		map = map->vm_next;
+	if (!map) {
+		up_read(&mm->mmap_sem);
+		mmput(mm);
 	}
-	up_read(&mm->mmap_sem);
-	mmput(mm);
+	return map;
+}
+
+static void m_stop(struct seq_file *m, void *v)
+{
+	struct vm_area_struct *map = v;
+	if (map) {
+		struct mm_struct *mm = map->vm_mm;
+		up_read(&mm->mmap_sem);
+		mmput(mm);
+	}
+}
 
-	if (retval > count) BUG();
-	if (copy_to_user(buf, kbuf, retval))
-		retval = -EFAULT;
-	else
-		*ppos = (lineno << PAGE_SHIFT) + loff;
-
-out_free2:
-	free_page((unsigned long)tmp);
-out_free1:
-	free_page((unsigned long)kbuf);
-out:
-	return retval;
+static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct vm_area_struct *map = v;
+	(*pos)++;
+	if (map->vm_next)
+		return map->vm_next;
+	m_stop(m, v);
+	return NULL;
 }
+
+struct seq_operations proc_pid_maps_op = {
+	.start	= m_start,
+	.next	= m_next,
+	.stop	= m_stop,
+	.show	= show_map
+};
diff -urN linux-2.5.69-bk14/fs/seq_file.c linux-2.5.69-bk15/fs/seq_file.c
--- linux-2.5.69-bk14/fs/seq_file.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/fs/seq_file.c	2003-05-21 04:47:34.000000000 -0700
@@ -297,6 +297,37 @@
 	return -1;
 }
 
+int seq_path(struct seq_file *m,
+		struct vfsmount *mnt, struct dentry *dentry,
+		char *esc)
+{
+	if (m->count < m->size) {
+		char *s = m->buf + m->count;
+		char *p = d_path(dentry, mnt, s, m->size - m->count);
+		if (!IS_ERR(p)) {
+			while (s <= p) {
+				char c = *p++;
+				if (!c) {
+					p = m->buf + m->count;
+					m->count = s - m->buf;
+					return s - p;
+				} else if (!strchr(esc, c)) {
+					*s++ = c;
+				} else if (s + 4 > p) {
+					break;
+				} else {
+					*s++ = '\\';
+					*s++ = '0' + ((c & 0300) >> 6);
+					*s++ = '0' + ((c & 070) >> 3);
+					*s++ = '0' + (c & 07);
+				}
+			}
+		}
+	}
+	m->count = m->size;
+	return -1;
+}
+
 static void *single_start(struct seq_file *p, loff_t *pos)
 {
 	return NULL + (*pos == 0);
diff -urN linux-2.5.69-bk14/fs/sysfs/symlink.c linux-2.5.69-bk15/fs/sysfs/symlink.c
--- linux-2.5.69-bk14/fs/sysfs/symlink.c	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/fs/sysfs/symlink.c	2003-05-04 16:53:14.000000000 -0700
@@ -80,7 +80,7 @@
 	char * s;
 
 	depth = object_depth(kobj);
-	size = object_path_length(target) + depth * 3 + 1;
+	size = object_path_length(target) + depth * 3 - 1;
 	if (size > PATH_MAX)
 		return -ENAMETOOLONG;
 	pr_debug("%s: depth = %d, size = %d\n",__FUNCTION__,depth,size);
diff -urN linux-2.5.69-bk14/include/asm-ppc64/compat.h linux-2.5.69-bk15/include/asm-ppc64/compat.h
--- linux-2.5.69-bk14/include/asm-ppc64/compat.h	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk15/include/asm-ppc64/compat.h	2003-05-21 04:47:34.000000000 -0700
@@ -119,4 +119,19 @@
 	return (void *)(unsigned long)uptr;
 }
 
+static inline void *compat_alloc_user_space(long len)
+{
+	struct pt_regs *regs = current->thread.regs;
+	unsigned long usp = regs->gpr[1];
+
+	/*
+	 * We cant access below the stack pointer in the 32bit ABI and
+	 * can access 288 bytes in the 64bit ABI
+	 */
+	if (!(test_thread_flag(TIF_32BIT)))
+		usp -= 288;
+
+	return (void *) (usp - len);
+}
+
 #endif /* _ASM_PPC64_COMPAT_H */
diff -urN linux-2.5.69-bk14/include/asm-sparc64/compat.h linux-2.5.69-bk15/include/asm-sparc64/compat.h
--- linux-2.5.69-bk14/include/asm-sparc64/compat.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/include/asm-sparc64/compat.h	2003-05-21 04:47:35.000000000 -0700
@@ -120,4 +120,15 @@
 	return (void *)(unsigned long)uptr;
 }
 
+static __inline__ void *compat_alloc_user_space(long len)
+{
+	struct pt_regs *regs = current_thread_info()->kregs;
+	unsigned long usp = regs->u_regs[UREG_I6];
+
+	if (!(test_thread_flag(TIF_32BIT)))
+		usp += STACK_BIAS;
+
+	return (void *) (usp - len);
+}
+
 #endif /* _ASM_SPARC64_COMPAT_H */
diff -urN linux-2.5.69-bk14/include/asm-x86_64/compat.h linux-2.5.69-bk15/include/asm-x86_64/compat.h
--- linux-2.5.69-bk14/include/asm-x86_64/compat.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk15/include/asm-x86_64/compat.h	2003-05-21 04:47:35.000000000 -0700
@@ -128,4 +128,10 @@
 	return (void *)(unsigned long)uptr;
 }
 
+static __inline__ void *compat_alloc_user_space(long len)
+{
+	struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs); 
+	return (void *)regs->rsp - len; 
+}
+
 #endif /* _ASM_X86_64_COMPAT_H */
diff -urN linux-2.5.69-bk14/include/linux/cyclomx.h linux-2.5.69-bk15/include/linux/cyclomx.h
--- linux-2.5.69-bk14/include/linux/cyclomx.h	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/cyclomx.h	2003-05-21 04:47:35.000000000 -0700
@@ -71,10 +71,10 @@
 };
 
 /* Public Functions */
-void cyclomx_set_state(struct cycx_device *card, int state);
+void cycx_set_state(struct cycx_device *card, int state);
 
 #ifdef CONFIG_CYCLOMX_X25
-int cyx_init(struct cycx_device *card, wandev_conf_t *conf);
+int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf);
 #endif
 #endif	/* __KERNEL__ */
 #endif	/* _CYCLOMX_H */
diff -urN linux-2.5.69-bk14/include/linux/divert.h linux-2.5.69-bk15/include/linux/divert.h
--- linux-2.5.69-bk14/include/linux/divert.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/divert.h	2003-05-21 04:47:35.000000000 -0700
@@ -107,11 +107,24 @@
 
 /* diverter functions */
 #include <linux/skbuff.h>
+
+#ifdef CONFIG_NET_DIVERT
 int alloc_divert_blk(struct net_device *);
 void free_divert_blk(struct net_device *);
 int divert_ioctl(unsigned int cmd, struct divert_cf *arg);
 void divert_frame(struct sk_buff *skb);
+static inline void handle_diverter(struct sk_buff *skb)
+{
+	/* if diversion is supported on device, then divert */
+	if (skb->dev->divert && skb->dev->divert->divert)
+		divert_frame(skb);
+}
 
+#else
+# define alloc_divert_blk(dev)		(0)
+# define free_divert_blk(dev)		do {} while (0)
+# define divert_ioctl(cmd, arg)		(-ENOPKG)
+# define handle_diverter(skb)		do {} while (0)
+#endif
 #endif 
-
 #endif	/* _LINUX_DIVERT_H */
diff -urN linux-2.5.69-bk14/include/linux/kernel.h linux-2.5.69-bk15/include/linux/kernel.h
--- linux-2.5.69-bk14/include/linux/kernel.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/kernel.h	2003-05-21 04:47:35.000000000 -0700
@@ -82,8 +82,6 @@
 extern int get_option(char **str, int *pint);
 extern char *get_options(const char *str, int nints, int *ints);
 extern unsigned long long memparse(char *ptr, char **retptr);
-extern void dev_probe_lock(void);
-extern void dev_probe_unlock(void);
 
 extern int kernel_text_address(unsigned long addr);
 extern int session_of_pgrp(int pgrp);
@@ -136,6 +134,16 @@
 	((unsigned char *)&addr)[2], \
 	((unsigned char *)&addr)[3]
 
+#define NIP6(addr) \
+	ntohs((addr).s6_addr16[0]), \
+	ntohs((addr).s6_addr16[1]), \
+	ntohs((addr).s6_addr16[2]), \
+	ntohs((addr).s6_addr16[3]), \
+	ntohs((addr).s6_addr16[4]), \
+	ntohs((addr).s6_addr16[5]), \
+	ntohs((addr).s6_addr16[6]), \
+	ntohs((addr).s6_addr16[7])
+
 #if defined(__LITTLE_ENDIAN)
 #define HIPQUAD(addr) \
 	((unsigned char *)&addr)[3], \
diff -urN linux-2.5.69-bk14/include/linux/module.h linux-2.5.69-bk15/include/linux/module.h
--- linux-2.5.69-bk14/include/linux/module.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/module.h	2003-05-21 04:47:35.000000000 -0700
@@ -437,7 +437,6 @@
 #endif /* MODULE */
 
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
-#define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE)
 
 /* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
 
diff -urN linux-2.5.69-bk14/include/linux/netdevice.h linux-2.5.69-bk15/include/linux/netdevice.h
--- linux-2.5.69-bk14/include/linux/netdevice.h	2003-05-21 04:47:24.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/netdevice.h	2003-05-21 04:47:35.000000000 -0700
@@ -28,7 +28,7 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
-#include <linux/kobject.h>
+#include <linux/device.h>
 
 #include <asm/atomic.h>
 #include <asm/cache.h>
@@ -427,9 +427,6 @@
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
 
-	/* open/release and usage marking */
-	struct module *owner;
-
 	/* bridge stuff */
 	struct net_bridge_port	*br_port;
 
@@ -444,10 +441,22 @@
 	struct divert_blk	*divert;
 #endif /* CONFIG_NET_DIVERT */
 
-	/* generic object representation */
-	struct kobject kobj;
+	/* generic device structure used in constructing class */
+	struct device		*dev;
+
+	/* class/net/name entry */
+	struct class_device	class_dev;
+
+	/* statistics sub-directory */
+	struct kobject		stats_kobj;
 };
 
+#define SET_MODULE_OWNER(dev) do { } while (0)
+/* Set the sysfs physical device reference for the network logical device
+ * if set prior to registration will cause a symlink during initialization.
+ */
+#define SET_NETDEV_DEV(net, pdev)	((net)->dev = (pdev))
+
 
 struct packet_type 
 {
@@ -563,12 +572,12 @@
 	set_bit(__LINK_STATE_XOFF, &dev->state);
 }
 
-static inline int netif_queue_stopped(struct net_device *dev)
+static inline int netif_queue_stopped(const struct net_device *dev)
 {
 	return test_bit(__LINK_STATE_XOFF, &dev->state);
 }
 
-static inline int netif_running(struct net_device *dev)
+static inline int netif_running(const struct net_device *dev)
 {
 	return test_bit(__LINK_STATE_START, &dev->state);
 }
@@ -608,7 +617,9 @@
 #define HAVE_NETIF_RECEIVE_SKB 1
 extern int		netif_receive_skb(struct sk_buff *skb);
 extern int		dev_ioctl(unsigned int cmd, void *);
+extern unsigned		dev_get_flags(const struct net_device *);
 extern int		dev_change_flags(struct net_device *, unsigned);
+extern int		dev_set_mtu(struct net_device *, int);
 extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
 
 extern void		dev_init(void);
@@ -626,12 +637,12 @@
        return err;
 }
 
-extern int netdev_finish_unregister(struct net_device *dev);
+/* Called by rtnetlink.c:rtnl_unlock() */
+extern void netdev_run_todo(void);
 
 static inline void dev_put(struct net_device *dev)
 {
-	if (atomic_dec_and_test(&dev->refcnt))
-		netdev_finish_unregister(dev);
+	atomic_dec(&dev->refcnt);
 }
 
 #define __dev_put(dev) atomic_dec(&(dev)->refcnt)
@@ -644,7 +655,7 @@
 
 extern void linkwatch_fire_event(struct net_device *dev);
 
-static inline int netif_carrier_ok(struct net_device *dev)
+static inline int netif_carrier_ok(const struct net_device *dev)
 {
 	return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
 }
diff -urN linux-2.5.69-bk14/include/linux/nfs.h linux-2.5.69-bk15/include/linux/nfs.h
--- linux-2.5.69-bk14/include/linux/nfs.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/nfs.h	2003-05-21 04:47:35.000000000 -0700
@@ -85,9 +85,9 @@
 	NFSERR_NOFILEHANDLE = 10020,	/*       v4 */
 	NFSERR_MINOR_VERS_MISMATCH = 10021,   /* v4 */
 	NFSERR_STALE_CLIENTID = 10022,	/*       v4 */
-	NFSERR_STALE_STATEID = 10023,	/*       v4 */
-	NFSERR_OLD_STATEID = 10024,	/*       v4 */
-	NFSERR_BAD_STATEID = 10025,	/*       v4 */
+	NFSERR_STALE_STATEID = 10023,   /*       v4 */
+	NFSERR_OLD_STATEID = 10024,     /*       v4 */
+	NFSERR_BAD_STATEID = 10025,     /*       v4 */  
 	NFSERR_BAD_SEQID = 10026,	/*       v4 */
 	NFSERR_NOT_SAME = 10027,	/*       v4 */
 	NFSERR_LOCK_RANGE = 10028,	/*       v4 */
@@ -99,7 +99,8 @@
 	NFSERR_RECLAIM_BAD = 10034,	/*       v4 */
 	NFSERR_RECLAIM_CONFLICT = 10035,/*       v4 */
 	NFSERR_BAD_XDR = 10036,		/*       v4 */
-	NFSERR_LOCKS_HELD = 10037	/*       v4 */
+	NFSERR_LOCKS_HELD = 10037,	/*       v4 */
+	NFSERR_REPLAY_ME = 10038	/*       v4 */
 };
 
 /* NFSv2 file types - beware, these are not the same in NFSv3 */
diff -urN linux-2.5.69-bk14/include/linux/nfsd/export.h linux-2.5.69-bk15/include/linux/nfsd/export.h
--- linux-2.5.69-bk14/include/linux/nfsd/export.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/nfsd/export.h	2003-05-21 04:47:35.000000000 -0700
@@ -100,7 +100,7 @@
 				   struct cache_req *reqp);
 int			exp_rootfh(struct auth_domain *, 
 					char *path, struct knfsd_fh *, int maxsize);
-int			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp);
+int			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
 int			nfserrno(int errno);
 
 extern void expkey_put(struct cache_head *item, struct cache_detail *cd);
diff -urN linux-2.5.69-bk14/include/linux/nfsd/nfsd.h linux-2.5.69-bk15/include/linux/nfsd/nfsd.h
--- linux-2.5.69-bk14/include/linux/nfsd/nfsd.h	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/nfsd/nfsd.h	2003-05-21 04:47:35.000000000 -0700
@@ -40,7 +40,7 @@
 #define MAY_OWNER_OVERRIDE	64
 #define	MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
 #if (MAY_SATTR | MAY_TRUNC | MAY_LOCK | MAY_OWNER_OVERRIDE | MAY_LOCAL_ACCESS) & (MAY_READ | MAY_WRITE | MAY_EXEC)
-# error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK or MAY_OWNER_OVERRIDE."
+# error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK or MAY_LOCAL_ACCESS or MAY_OWNER_OVERRIDE."
 #endif
 #define MAY_CREATE		(MAY_EXEC|MAY_WRITE)
 #define MAY_REMOVE		(MAY_EXEC|MAY_WRITE|MAY_TRUNC)
@@ -170,6 +170,7 @@
 #define	nfserr_serverfault	__constant_htonl(NFSERR_SERVERFAULT)
 #define	nfserr_badtype		__constant_htonl(NFSERR_BADTYPE)
 #define	nfserr_jukebox		__constant_htonl(NFSERR_JUKEBOX)
+#define nfserr_expired          __constant_htonl(NFSERR_EXPIRED)
 #define	nfserr_bad_cookie	__constant_htonl(NFSERR_BAD_COOKIE)
 #define	nfserr_same		__constant_htonl(NFSERR_SAME)
 #define	nfserr_clid_inuse	__constant_htonl(NFSERR_CLID_INUSE)
@@ -177,6 +178,11 @@
 #define	nfserr_resource		__constant_htonl(NFSERR_RESOURCE)
 #define	nfserr_nofilehandle	__constant_htonl(NFSERR_NOFILEHANDLE)
 #define	nfserr_minor_vers_mismatch	__constant_htonl(NFSERR_MINOR_VERS_MISMATCH)
+#define nfserr_share_denied	__constant_htonl(NFSERR_SHARE_DENIED)
+#define nfserr_stale_stateid	__constant_htonl(NFSERR_STALE_STATEID)
+#define nfserr_old_stateid	__constant_htonl(NFSERR_OLD_STATEID)
+#define nfserr_bad_stateid	__constant_htonl(NFSERR_BAD_STATEID)
+#define nfserr_bad_seqid	__constant_htonl(NFSERR_BAD_SEQID)
 #define	nfserr_symlink		__constant_htonl(NFSERR_SYMLINK)
 #define	nfserr_not_same		__constant_htonl(NFSERR_NOT_SAME)
 #define	nfserr_readdir_nospc	__constant_htonl(NFSERR_READDIR_NOSPC)
diff -urN linux-2.5.69-bk14/include/linux/nfsd/state.h linux-2.5.69-bk15/include/linux/nfsd/state.h
--- linux-2.5.69-bk14/include/linux/nfsd/state.h	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/nfsd/state.h	2003-05-21 04:47:35.000000000 -0700
@@ -39,9 +39,25 @@
 
 #include <linux/list.h>
 
-#define NFSD4_CLIENT_MAXNAME 1024
+#define NFS4_OPAQUE_LIMIT 1024
+typedef struct {
+	u32             cl_boot;
+	u32             cl_id;
+} clientid_t;
 
-extern int nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid);
+typedef struct {
+	u32             so_boot;
+	u32             so_stateownerid;
+	u32             so_fileid;
+} stateid_opaque_t;
+
+typedef struct {
+	u32                     si_generation;
+	stateid_opaque_t        si_opaque;
+} stateid_t;
+#define si_boot           si_opaque.so_boot
+#define si_stateownerid   si_opaque.so_stateownerid
+#define si_fileid         si_opaque.so_fileid
 
 /*
  * struct nfs4_client - one per client.  Clientids live here.
@@ -49,10 +65,14 @@
  *
  * 	o Each nfs4_clients is also hashed by name 
  * 	  (the opaque quantity initially sent by the client to identify itself).
+ * 	  
+ *	o cl_perclient list is used to ensure no dangling stateowner references
+ *	  when we expire the nfs4_client
  */
 struct nfs4_client {
 	struct list_head	cl_idhash; 	/* hash by cl_clientid.id */
 	struct list_head	cl_strhash; 	/* hash by cl_name */
+	struct list_head	cl_perclient; 	/* list: stateowners */
 	struct xdr_netobj	cl_name; 	/* id generated by client */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	u32			cl_addr; 	/* client ipaddress */
@@ -60,4 +80,66 @@
 	clientid_t		cl_clientid;	/* generated by server */
 	nfs4_verifier		cl_confirm;	/* generated by server */
 };
+
+static inline void
+update_stateid(stateid_t *stateid)
+{
+stateid->si_generation++;
+}
+
+
+/*
+* nfs4_stateowner can either be an open_owner, or (eventually) a lock_owner
+*
+*    o so_peropenstate list is used to ensure no dangling nfs4_stateid
+*              reverences when we release a stateowner.
+*/
+struct nfs4_stateowner {
+	struct list_head        so_strhash;   /* hash by op_name */
+	struct list_head        so_perclient; /* nfs4_client->cl_perclient */
+	struct list_head        so_peropenstate; /* list: nfs4_stateid */
+	u32                     so_id;
+	struct nfs4_client *    so_client;
+	u32                     so_seqid;    
+	struct xdr_netobj       so_owner;     /* open owner name */
+	int                     so_confirmed; /* successful OPEN_CONFIRM? */
+};
+
+typedef struct {
+	u32                     dev; /* super_block->s_dev */
+	unsigned long           ino;
+	u32                     generation;
+} nfs4_ino_desc_t;
+
+/*
+*  nfs4_file: a file opened by some number of (open) nfs4_stateowners.
+*    o fi_perfile list is used to search for conflicting 
+*      share_acces, share_deny on the file.
+*/
+struct nfs4_file {
+	struct list_head        fi_hash;    /* hash by nfs4_ino_desc_t fields */
+	struct list_head        fi_perfile; /* list: nfs4_stateid */
+	nfs4_ino_desc_t         fi_ino;
+	u32                     fi_id;      /* used with stateowner->so_id 
+					     * for openstateid_hashtbl hash */
+};
+
+/*
+* nfs4_stateid can either be an open stateid or (eventually) a lock stateid
+*
+* (open)nfs4_stateid: one per (open)nfs4_stateowner, nfs4_file
+*/
+
+struct nfs4_stateid {
+	struct list_head              st_perfile; /* file_hashtbl[]*/
+	struct list_head              st_peropenstate; /* nfs4_stateowner->so_peropenstate */
+	struct nfs4_stateowner      * st_stateowner;
+	struct nfs4_file            * st_file;
+	stateid_t                     st_stateid;
+	struct file                   st_vfs_file;
+	int                           st_vfs_set;
+	unsigned int                  st_share_access;
+	unsigned int                  st_share_deny;
+};
+
 #endif   /* NFSD4_STATE_H */
diff -urN linux-2.5.69-bk14/include/linux/nfsd/xdr4.h linux-2.5.69-bk15/include/linux/nfsd/xdr4.h
--- linux-2.5.69-bk14/include/linux/nfsd/xdr4.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/nfsd/xdr4.h	2003-05-21 04:47:35.000000000 -0700
@@ -41,27 +41,6 @@
 
 #define NFSD4_MAX_TAGLEN	128
 
-typedef struct {
-	u32		cl_boot;
-	u32		cl_id;
-} clientid_t;
-
-typedef u32 stateid_boot_t;        /* used to detect stale stateids */
-typedef u32 stateid_lockowner_t;   /* lockowner id - used in various places */
-typedef u32 stateid_file_t;        /* identifies a unique file per lockowner */
-typedef u32 stateid_generation_t;  /* used to update stateids */
-
-typedef struct {
-	stateid_boot_t		so_boot;
-	stateid_lockowner_t	so_lockowner;
-	stateid_file_t		so_file;
-} stateid_other_t;
-
-typedef struct {
-	stateid_generation_t	st_generation;
-	stateid_other_t		st_other;
-} stateid_t;
-
 typedef u32 delegation_zero_t;
 typedef u32 delegation_boot_t;
 typedef u64 delegation_id_t;
@@ -143,8 +122,7 @@
 
 struct nfsd4_open {
 	u32		op_claim_type;      /* request */
-	u32		op_namelen;	    /* request - everything but CLAIM_PREV */
-	char *		op_name;	    /* request - everything but CLAIM_PREV */
+	struct xdr_netobj op_fname;	    /* request - everything but CLAIM_PREV */
 	u32		op_delegate_type;   /* request - CLAIM_PREV only */
 	delegation_stateid_t	op_delegate_stateid; /* request - CLAIM_DELEGATE_CUR only */
 	u32		op_create;     	    /* request */
@@ -155,8 +133,7 @@
 		nfs4_verifier	verf;		                     /* EXCLUSIVE4 */
 	} u;
 	clientid_t	op_clientid;        /* request */
-	u32		op_ownerlen;        /* request */
-	char *		op_owner;           /* request */
+	struct xdr_netobj op_owner;           /* request */
 	u32		op_seqid;           /* request */
 	u32		op_share_access;    /* request */
 	u32		op_share_deny;      /* request */
@@ -164,6 +141,7 @@
 	struct nfsd4_change_info  op_cinfo; /* response */
 	u32		op_rflags;          /* response */
 	int		op_truncate;        /* used during processing */
+	struct nfs4_stateowner *op_stateowner; /* used during processing */
 
 };
 #define op_iattr	u.iattr
@@ -343,7 +321,10 @@
 void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
 int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 		       struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval);
-
+extern int nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid);
+extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm);
+extern int nfsd4_process_open1(struct nfsd4_open *open);
+extern int nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open);
 #endif
 
 /*
diff -urN linux-2.5.69-bk14/include/linux/seq_file.h linux-2.5.69-bk15/include/linux/seq_file.h
--- linux-2.5.69-bk14/include/linux/seq_file.h	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/include/linux/seq_file.h	2003-05-21 04:47:35.000000000 -0700
@@ -8,6 +8,8 @@
 
 struct seq_operations;
 struct file;
+struct vfsmount;
+struct dentry;
 struct inode;
 
 struct seq_file {
@@ -58,6 +60,8 @@
 int seq_printf(struct seq_file *, const char *, ...)
 	__attribute__ ((format (printf,2,3)));
 
+int seq_path(struct seq_file *, struct vfsmount *, struct dentry *, char *);
+
 int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
 int single_release(struct inode *, struct file *);
 int seq_release_private(struct inode *, struct file *);
diff -urN linux-2.5.69-bk14/include/net/sock.h linux-2.5.69-bk15/include/net/sock.h
--- linux-2.5.69-bk14/include/net/sock.h	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/include/net/sock.h	2003-05-21 04:47:35.000000000 -0700
@@ -95,41 +95,109 @@
 	init_waitqueue_head(&((__sk)->lock.wq)); \
 } while(0)
 
+/**
+  *	struct sock - network layer representation of sockets
+  *	@state - Connection state
+  *	@zapped	- ax25 & ipx means !linked
+  *	@reuse - %SO_REUSEADDR setting
+  *	@shutdown - mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
+  *	@bound_dev_if - bound device index if != 0
+  *	@next - main hash linkage for various protocol lookup tables
+  *	@pprev - main hash linkage for various protocol lookup tables
+  *	@bind_next - main hash linkage for various protocol lookup tables
+  *	@bind_pprev - main hash linkage for various protocol lookup tables
+  *	@refcnt - reference count
+  *	@family - network address family
+  *	@use_write_queue - wheter to call sk->write_space(sk) in sock_wfree
+  *	@userlocks - %SO_SNDBUF and %SO_RCVBUF settings
+  *	@lock -	synchronizer
+  *	@rcvbuf - size of receive buffer in bytes
+  *	@sleep - sock wait queue
+  *	@dst_cache - destination cache
+  *	@dst_lock - destination cache lock
+  *	@policy - flow policy
+  *	@rmem_alloc - receive queue bytes committed
+  *	@receive_queue - incoming packets
+  *	@wmem_alloc - transmit queue bytes committed
+  *	@write_queue - Packet sending queue
+  *	@omem_alloc - "o" is "option" or "other"
+  *	@wmem_queued - persistent queue size
+  *	@forward_alloc - space allocated forward
+  *	@allocation - allocation mode
+  *	@sndbuf - size of send buffer in bytes
+  *	@prev - pointer to previous sock in the list this sock is in
+  *	@flags - %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings
+  *	@no_check - %SO_NO_CHECK setting, wether or not checkup packets
+  *	@debug - %SO_DEBUG setting
+  *	@rcvtstamp - %SO_TIMESTAMP setting
+  *	@no_largesend - whether to sent large segments or not
+  *	@route_caps - route capabilities (e.g. %NETIF_F_TSO)
+  *	@lingertime - %SO_LINGER l_linger setting
+  *	@hashent - hash entry in several tables (e.g. tcp_ehash)
+  *	@pair - socket pair (e.g. AF_UNIX/unix_peer)
+  *	@backlog - always used with the per-socket spinlock held
+  *	@callback_lock - used with the callbacks in the end of this struct
+  *	@error_queue - rarely used
+  *	@prot - protocol handlers inside a network family
+  *	@err - last error
+  *	@err_soft - errors that don't cause failure but are the cause of a persistent failure not just 'timed out'
+  *	@ack_backlog - current listen backlog
+  *	@max_ack_backlog - listen backlog set in listen()
+  *	@priority - %SO_PRIORITY setting
+  *	@type - socket type (%SOCK_STREAM, etc)
+  *	@localroute - route locally only, %SO_DONTROUTE setting
+  *	@protocol - which protocol this socket belongs in this network family
+  *	@peercred - %SO_PEERCRED setting
+  *	@rcvlowat - %SO_RCVLOWAT setting
+  *	@rcvtimeo - %SO_RCVTIMEO setting
+  *	@sndtimeo - %SO_SNDTIMEO setting
+  *	@filter - socket filtering instructions
+  *	@protinfo - private area, net family specific, when not using slab
+  *	@slab - the slabcache this instance was allocated from
+  *	@timer - sock cleanup timer
+  *	@stamp - time stamp of last packet received
+  *	@socket - Identd and reporting IO signals
+  *	@user_data - RPC layer private data
+  *	@owner - module that owns this socket
+  *	@state_change - callback to indicate change in the state of the sock
+  *	@data_ready - callback to indicate there is data to be processed
+  *	@write_space - callback to indicate there is bf sending space available
+  *	@error_report - callback to indicate errors (e.g. %MSG_ERRQUEUE)
+  *	@backlog_rcv - callback to process the backlog
+  *	@destruct - called at sock freeing time, i.e. when all refcnt == 0
+ */
 struct sock {
 	/* Begin of struct sock/struct tcp_tw_bucket shared layout */
-	volatile unsigned char	state,		/* Connection state */
-				zapped;		/* ax25 & ipx means !linked */
-	unsigned char		reuse;		/* SO_REUSEADDR setting */
+	volatile unsigned char	state,
+				zapped;
+	unsigned char		reuse;
 	unsigned char		shutdown;
-	int			bound_dev_if;	/* Bound device index if != 0 */
-	/* Main hash linkage for various protocol lookup tables. */
+	int			bound_dev_if;
 	struct sock		*next;
 	struct sock		**pprev;
 	struct sock		*bind_next;
 	struct sock		**bind_pprev;
-	atomic_t		refcnt;		/* Reference count			*/
-	unsigned short		family;		/* Address family */
+	atomic_t		refcnt;
+	unsigned short		family;
 	/* End of struct sock/struct tcp_tw_bucket shared layout */
 	unsigned char		use_write_queue;
 	unsigned char		userlocks;
-	socket_lock_t		lock;		/* Synchronizer...			*/
-	int			rcvbuf;		/* Size of receive buffer in bytes	*/
-
-	wait_queue_head_t	*sleep;		/* Sock wait queue			*/
-	struct dst_entry	*dst_cache;	/* Destination cache			*/
+	socket_lock_t		lock;
+	int			rcvbuf;
+	wait_queue_head_t	*sleep;
+	struct dst_entry	*dst_cache;
 	rwlock_t		dst_lock;
 	struct xfrm_policy	*policy[2];
-	atomic_t		rmem_alloc;	/* Receive queue bytes committed	*/
-	struct sk_buff_head	receive_queue;	/* Incoming packets			*/
-	atomic_t		wmem_alloc;	/* Transmit queue bytes committed	*/
-	struct sk_buff_head	write_queue;	/* Packet sending queue			*/
-	atomic_t		omem_alloc;	/* "o" is "option" or "other" */
-	int			wmem_queued;	/* Persistent queue size */
-	int			forward_alloc;	/* Space allocated forward. */
-	unsigned int		allocation;	/* Allocation mode			*/
-	int			sndbuf;		/* Size of send buffer in bytes		*/
+	atomic_t		rmem_alloc;
+	struct sk_buff_head	receive_queue;
+	atomic_t		wmem_alloc;
+	struct sk_buff_head	write_queue;
+	atomic_t		omem_alloc;
+	int			wmem_queued;
+	int			forward_alloc;
+	unsigned int		allocation;
+	int			sndbuf;
 	struct sock		*prev;
-
 	unsigned long 		flags;
 	char		 	no_check;
 	unsigned char		debug;
@@ -137,72 +205,44 @@
 	unsigned char		no_largesend;
 	int			route_caps;
 	unsigned long	        lingertime;
-
 	int			hashent;
 	struct sock		*pair;
-
-	/* The backlog queue is special, it is always used with
+	/*
+	 * The backlog queue is special, it is always used with
 	 * the per-socket spinlock held and requires low latency
-	 * access.  Therefore we special case it's implementation.
+	 * access. Therefore we special case it's implementation.
 	 */
 	struct {
 		struct sk_buff *head;
 		struct sk_buff *tail;
 	} backlog;
-
 	rwlock_t		callback_lock;
-
-	/* Error queue, rarely used. */
 	struct sk_buff_head	error_queue;
-
 	struct proto		*prot;
-
-	int			err, err_soft;	/* Soft holds errors that don't
-						   cause failure but are the cause
-						   of a persistent failure not just
-						   'timed out' */
+	int			err,
+				err_soft;
 	unsigned short		ack_backlog;
 	unsigned short		max_ack_backlog;
 	__u32			priority;
 	unsigned short		type;
-	unsigned char		localroute;	/* Route locally only */
+	unsigned char		localroute;
 	unsigned char		protocol;
 	struct ucred		peercred;
 	int			rcvlowat;
 	long			rcvtimeo;
 	long			sndtimeo;
-
-	/* Socket Filtering Instructions */
 	struct sk_filter      	*filter;
-
-	/* This is where all the private (optional) areas that don't
-	 * overlap will eventually live. 
-	 */
-	void *protinfo;
-
-	/* The slabcache this instance was allocated from, it is sk_cachep for most
-	 * protocols, but a private slab for protocols such as IPv4, IPv6, SPX
-	 * and Unix.
-	 */
-	kmem_cache_t *slab;
-
-	/* This part is used for the timeout functions. */
-	struct timer_list	timer;		/* This is the sock cleanup timer. */
+	void			*protinfo;
+	kmem_cache_t		*slab;
+	struct timer_list	timer;
 	struct timeval		stamp;
-
-	/* Identd and reporting IO signals */
 	struct socket		*socket;
-
-	/* RPC layer private data */
 	void			*user_data;
-  
-	/* Callbacks */
 	struct module		*owner;
 	void			(*state_change)(struct sock *sk);
-	void			(*data_ready)(struct sock *sk,int bytes);
+	void			(*data_ready)(struct sock *sk, int bytes);
 	void			(*write_space)(struct sock *sk);
 	void			(*error_report)(struct sock *sk);
-
   	int			(*backlog_rcv) (struct sock *sk,
 						struct sk_buff *skb);  
 	void                    (*destruct)(struct sock *sk);
diff -urN linux-2.5.69-bk14/kernel/kmod.c linux-2.5.69-bk15/kernel/kmod.c
--- linux-2.5.69-bk14/kernel/kmod.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/kernel/kmod.c	2003-05-21 04:47:35.000000000 -0700
@@ -264,22 +264,6 @@
 	return sub_info.retval;
 }
 
-/*
- * This is for the serialisation of device probe() functions
- * against device open() functions
- */
-static DECLARE_MUTEX(dev_probe_sem);
-
-void dev_probe_lock(void)
-{
-	down(&dev_probe_sem);
-}
-
-void dev_probe_unlock(void)
-{
-	up(&dev_probe_sem);
-}
-
 EXPORT_SYMBOL(call_usermodehelper);
 
 #ifdef CONFIG_KMOD
diff -urN linux-2.5.69-bk14/mm/swapfile.c linux-2.5.69-bk15/mm/swapfile.c
--- linux-2.5.69-bk14/mm/swapfile.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/mm/swapfile.c	2003-05-21 04:47:35.000000000 -0700
@@ -1118,14 +1118,9 @@
 	struct swap_info_struct *ptr = swap_info;
 	int i;
 	loff_t l = *pos;
-	char * page = (char *) __get_free_page(GFP_KERNEL);
 
-	swap->private = page;	/* save for swap_show */
 	swap_list_lock();
 
-	if (!page)
-		return ERR_PTR(-ENOMEM);
-
 	for (i = 0; i < nr_swapfiles; i++, ptr++) {
 		if (!(ptr->flags & SWP_USED) || !ptr->swap_map)
 			continue;
@@ -1154,24 +1149,21 @@
 static void swap_stop(struct seq_file *swap, void *v)
 {
 	swap_list_unlock();
-	free_page((unsigned long) swap->private);
-	swap->private = NULL;
 }
 
 static int swap_show(struct seq_file *swap, void *v)
 {
 	struct swap_info_struct *ptr = v;
 	struct file *file;
-	char *path;
+	int len;
 
 	if (v == swap_info)
 		seq_puts(swap, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
 
 	file = ptr->swap_file;
-	path = d_path(file->f_dentry, file->f_vfsmnt, swap->private, PAGE_SIZE);
-
-	seq_printf(swap, "%-39s %s\t%d\t%ld\t%d\n",
-		       path,
+	len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\");
+	seq_printf(swap, "%*s %s\t%d\t%ld\t%d\n",
+		       len < 40 ? 40 - len : 1, " ",
 		       S_ISBLK(file->f_dentry->d_inode->i_mode) ?
 				"partition" : "file\t",
 		       ptr->pages << (PAGE_SHIFT - 10),
diff -urN linux-2.5.69-bk14/net/8021q/vlan.c linux-2.5.69-bk15/net/8021q/vlan.c
--- linux-2.5.69-bk14/net/8021q/vlan.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk15/net/8021q/vlan.c	2003-05-21 04:47:35.000000000 -0700
@@ -454,7 +454,7 @@
 	/* set up method calls */
 	new_dev->init = vlan_dev_init;
 	new_dev->destructor = vlan_dev_destruct;
-	new_dev->owner = THIS_MODULE;
+	SET_MODULE_OWNER(new_dev);
 	    
 	/* new_dev->ifindex = 0;  it will be set when added to
 	 * the global list.
diff -urN linux-2.5.69-bk14/net/atm/common.c linux-2.5.69-bk15/net/atm/common.c
--- linux-2.5.69-bk14/net/atm/common.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/atm/common.c	2003-05-21 04:47:35.000000000 -0700
@@ -278,7 +278,8 @@
 	    vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
 	DPRINTK("  RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
 	    vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
-	__module_get(dev->ops->owner);
+	if (!try_module_get(dev->ops->owner))
+		return -ENODEV;
 	if (dev->ops->open) {
 		error = dev->ops->open(vcc,vpi,vci);
 		if (error) {
diff -urN linux-2.5.69-bk14/net/atm/proc.c linux-2.5.69-bk15/net/atm/proc.c
--- linux-2.5.69-bk14/net/atm/proc.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/atm/proc.c	2003-05-21 04:47:35.000000000 -0700
@@ -75,7 +75,7 @@
 }
 
 
-static void dev_info(const struct atm_dev *dev,char *buf)
+static void atm_dev_info(const struct atm_dev *dev,char *buf)
 {
 	int off,i;
 
@@ -319,7 +319,7 @@
 	list_for_each(p, &atm_devs) {
 		dev = list_entry(p, struct atm_dev, dev_list);
 		if (left-- == 0) {
-			dev_info(dev,buf);
+			atm_dev_info(dev,buf);
 			spin_unlock(&atm_dev_lock);
 			return strlen(buf);
 		}
diff -urN linux-2.5.69-bk14/net/bridge/br_device.c linux-2.5.69-bk15/net/bridge/br_device.c
--- linux-2.5.69-bk14/net/bridge/br_device.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/net/bridge/br_device.c	2003-05-21 04:47:36.000000000 -0700
@@ -125,7 +125,7 @@
 	dev->open = br_dev_open;
 	dev->set_multicast_list = br_dev_set_multicast_list;
 	dev->destructor = br_dev_destruct;
-	dev->owner = THIS_MODULE;
+	SET_MODULE_OWNER(dev);
 	dev->stop = br_dev_stop;
 	dev->accept_fastpath = br_dev_accept_fastpath;
 	dev->tx_queue_len = 0;
diff -urN linux-2.5.69-bk14/net/bridge/br_if.c linux-2.5.69-bk15/net/bridge/br_if.c
--- linux-2.5.69-bk14/net/bridge/br_if.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/bridge/br_if.c	2003-05-21 04:47:36.000000000 -0700
@@ -277,8 +277,7 @@
 	rtnl_lock();
 	for (dev = dev_base; dev; dev = nxt) {
 		nxt = dev->next;
-		if ((dev->priv_flags & IFF_EBRIDGE)
-		    && dev->owner == THIS_MODULE) {
+		if (dev->priv_flags & IFF_EBRIDGE) {
 			pr_debug("cleanup %s\n", dev->name);
 
 			del_ifs((struct net_bridge *) dev->priv);
diff -urN linux-2.5.69-bk14/net/bridge/br_netfilter.c linux-2.5.69-bk15/net/bridge/br_netfilter.c
--- linux-2.5.69-bk14/net/bridge/br_netfilter.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk15/net/bridge/br_netfilter.c	2003-05-21 04:47:36.000000000 -0700
@@ -620,13 +620,11 @@
 	  .priority = NF_IP_PRI_FIRST, },
 };
 
-#define NUMHOOKS (sizeof(br_nf_ops)/sizeof(br_nf_ops[0]))
-
 int br_netfilter_init(void)
 {
 	int i;
 
-	for (i = 0; i < NUMHOOKS; i++) {
+	for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) {
 		int ret;
 
 		if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0)
@@ -647,6 +645,6 @@
 {
 	int i;
 
-	for (i = NUMHOOKS - 1; i >= 0; i--)
+	for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--)
 		nf_unregister_hook(&br_nf_ops[i]);
 }
diff -urN linux-2.5.69-bk14/net/bridge/netfilter/ebtable_filter.c linux-2.5.69-bk15/net/bridge/netfilter/ebtable_filter.c
--- linux-2.5.69-bk14/net/bridge/netfilter/ebtable_filter.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/net/bridge/netfilter/ebtable_filter.c	2003-05-21 04:47:36.000000000 -0700
@@ -98,7 +98,7 @@
 	ret = ebt_register_table(&frame_filter);
 	if (ret < 0)
 		return ret;
-	for (i = 0; i < sizeof(ebt_ops_filter) / sizeof(ebt_ops_filter[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
 		if ((ret = nf_register_hook(&ebt_ops_filter[i])) < 0)
 			goto cleanup;
 	return ret;
@@ -113,7 +113,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(ebt_ops_filter) / sizeof(ebt_ops_filter[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
 		nf_unregister_hook(&ebt_ops_filter[i]);
 	ebt_unregister_table(&frame_filter);
 }
diff -urN linux-2.5.69-bk14/net/bridge/netfilter/ebtable_nat.c linux-2.5.69-bk15/net/bridge/netfilter/ebtable_nat.c
--- linux-2.5.69-bk14/net/bridge/netfilter/ebtable_nat.c	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk15/net/bridge/netfilter/ebtable_nat.c	2003-05-21 04:47:36.000000000 -0700
@@ -10,6 +10,7 @@
 
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/module.h>
+
 #define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \
    (1 << NF_BR_POST_ROUTING))
 
@@ -104,7 +105,7 @@
 	ret = ebt_register_table(&frame_nat);
 	if (ret < 0)
 		return ret;
-	for (i = 0; i < sizeof(ebt_ops_nat) / sizeof(ebt_ops_nat[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
 		if ((ret = nf_register_hook(&ebt_ops_nat[i])) < 0)
 			goto cleanup;
 	return ret;
@@ -119,7 +120,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(ebt_ops_nat) / sizeof(ebt_ops_nat[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
 		nf_unregister_hook(&ebt_ops_nat[i]);
 	ebt_unregister_table(&frame_nat);
 }
diff -urN linux-2.5.69-bk14/net/compat.c linux-2.5.69-bk15/net/compat.c
--- linux-2.5.69-bk14/net/compat.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/compat.c	2003-05-21 04:47:36.000000000 -0700
@@ -389,30 +389,20 @@
 				char *optval, int optlen)
 {
 	struct compat_sock_fprog *fprog32 = (struct compat_sock_fprog *)optval;
-	struct sock_fprog kfprog;
-	mm_segment_t old_fs;
-	int ret;
+	struct sock_fprog *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); 
 	compat_uptr_t ptr;
+	u16 len;
 
 	if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) ||
-	    __get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(ptr, &fprog32->filter))
-		return -EFAULT;
-	kfprog.filter = compat_ptr(ptr);	
-
-	if (kfprog.len * sizeof(struct sock_filter) < kfprog.len) 
-		return -EINVAL;
-
-	if (verify_area(VERIFY_READ, kfprog.filter, 
-				    kfprog.len * sizeof(struct sock_filter)))
+	    !access_ok(VERIFY_WRITE, kfprog, sizeof(struct sock_fprog)) ||
+	    __get_user(len, &fprog32->len) ||
+	    __get_user(ptr, &fprog32->filter) ||
+	    __put_user(len, &kfprog->len) ||
+	    __put_user(compat_ptr(ptr), &kfprog->filter))
 		return -EFAULT;
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-	return ret;
+	return sys_setsockopt(fd, level, optname, (char *)kfprog, 
+			      sizeof(struct sock_fprog));
 }
 
 static int do_set_icmpv6_filter(int fd, int level, int optname,
diff -urN linux-2.5.69-bk14/net/core/Makefile linux-2.5.69-bk15/net/core/Makefile
--- linux-2.5.69-bk14/net/core/Makefile	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/core/Makefile	2003-05-21 04:47:36.000000000 -0700
@@ -10,7 +10,8 @@
 endif
 endif
 
-obj-$(CONFIG_NET) += flow.o dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o link_watch.o filter.o
+obj-$(CONFIG_NET) += flow.o dev.o net-sysfs.o dev_mcast.o dst.o neighbour.o \
+		     rtnetlink.o utils.o link_watch.o filter.o
 
 obj-$(CONFIG_NETFILTER) += netfilter.o
 obj-$(CONFIG_NET_DIVERT) += dv.o
diff -urN linux-2.5.69-bk14/net/core/dev.c linux-2.5.69-bk15/net/core/dev.c
--- linux-2.5.69-bk14/net/core/dev.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/core/dev.c	2003-05-21 04:47:36.000000000 -0700
@@ -131,16 +131,6 @@
 NET_PROFILE_DEFINE(dev_queue_xmit)
 NET_PROFILE_DEFINE(softnet_process)
 
-const char *if_port_text[] = {
-  "unknown",
-  "BNC",
-  "10baseT",
-  "AUI",
-  "100baseT",
-  "100baseTX",
-  "100baseFX"
-};
-
 /*
  *	The list of packet types we will receive (as opposed to discard)
  *	and the routines to invoke.
@@ -179,9 +169,11 @@
 #endif
 
 #ifdef CONFIG_HOTPLUG
-static int net_run_sbin_hotplug(struct net_device *dev, char *action);
+static void net_run_sbin_hotplug(struct net_device *dev, int is_register);
+static void net_run_hotplug_todo(void);
 #else
-#define net_run_sbin_hotplug(dev, action) ({ 0; })
+#define net_run_sbin_hotplug(dev, is_register) do { } while (0)
+#define net_run_hotplug_todo() do { } while (0)
 #endif
 
 /*
@@ -201,7 +193,9 @@
 int netdev_fastroute_obstacles;
 #endif
 
-static struct subsystem net_subsys;
+extern int netdev_sysfs_init(void);
+extern int netdev_register_sysfs(struct net_device *);
+extern void netdev_unregister_sysfs(struct net_device *);
 
 
 /*******************************************************************************
@@ -706,9 +700,6 @@
 	}
 }
 
-
-#ifdef CONFIG_KMOD
-
 /**
  *	dev_load 	- load a network module
  *	@name: name of interface
@@ -724,12 +715,6 @@
 		request_module("%s", name);
 }
 
-#else
-
-static inline void dev_load(const char *unused){;}
-
-#endif
-
 static int default_rebuild_header(struct sk_buff *skb)
 {
 	printk(KERN_DEBUG "%s: default_rebuild_header called -- BUG!\n",
@@ -770,17 +755,11 @@
 	/*
 	 *	Call device private open method
 	 */
-	if (try_module_get(dev->owner)) {
-		set_bit(__LINK_STATE_START, &dev->state);
-		if (dev->open) {
-			ret = dev->open(dev);
-			if (ret) {
-				clear_bit(__LINK_STATE_START, &dev->state);
-				module_put(dev->owner);
-			}
-		}
-	} else {
-		ret = -ENODEV;
+	set_bit(__LINK_STATE_START, &dev->state);
+	if (dev->open) {
+		ret = dev->open(dev);
+		if (ret)
+			clear_bit(__LINK_STATE_START, &dev->state);
 	}
 
 	/*
@@ -905,10 +884,6 @@
 	 */
 	notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
 
-	/*
-	 * Drop the module refcount
-	 */
-	module_put(dev->owner);
 	return 0;
 }
 
@@ -1482,15 +1457,6 @@
 
 #endif
 
-static inline void handle_diverter(struct sk_buff *skb)
-{
-#ifdef CONFIG_NET_DIVERT
-	/* if diversion is supported on device, then divert */
-	if (skb->dev->divert && skb->dev->divert->divert)
-		divert_frame(skb);
-#endif
-}
-
 static inline int __handle_bridge(struct sk_buff *skb,
 			struct packet_type **pt_prev, int *ret)
 {
@@ -2101,6 +2067,22 @@
 		dev_mc_upload(dev);
 }
 
+unsigned dev_get_flags(const struct net_device *dev)
+{
+	unsigned flags;
+
+	flags = (dev->flags & ~(IFF_PROMISC |
+				IFF_ALLMULTI |
+				IFF_RUNNING)) | 
+		(dev->gflags & (IFF_PROMISC |
+				IFF_ALLMULTI));
+
+	if (netif_running(dev) && netif_carrier_ok(dev))
+		flags |= IFF_RUNNING;
+
+	return flags;
+}
+
 int dev_change_flags(struct net_device *dev, unsigned flags)
 {
 	int ret;
@@ -2163,6 +2145,32 @@
 	return ret;
 }
 
+int dev_set_mtu(struct net_device *dev, int new_mtu)
+{
+	int err;
+
+	if (new_mtu == dev->mtu)
+		return 0;
+
+	/*	MTU must be positive.	 */
+	if (new_mtu < 0)
+		return -EINVAL;
+
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	err = 0;
+	if (dev->change_mtu)
+		err = dev->change_mtu(dev, new_mtu);
+	else
+		dev->mtu = new_mtu;
+	if (!err && dev->flags & IFF_UP)
+		notifier_call_chain(&netdev_chain,
+				    NETDEV_CHANGEMTU, dev);
+	return err;
+}
+
+
 /*
  *	Perform the SIOCxIFxxx calls.
  */
@@ -2176,13 +2184,7 @@
 
 	switch (cmd) {
 		case SIOCGIFFLAGS:	/* Get interface flags */
-			ifr->ifr_flags = (dev->flags & ~(IFF_PROMISC |
-							 IFF_ALLMULTI |
-							 IFF_RUNNING)) | 
-					 (dev->gflags & (IFF_PROMISC |
-							 IFF_ALLMULTI));
-			if (netif_running(dev) && netif_carrier_ok(dev))
-				ifr->ifr_flags |= IFF_RUNNING;
+			ifr->ifr_flags = dev_get_flags(dev);
 			return 0;
 
 		case SIOCSIFFLAGS:	/* Set interface flags */
@@ -2202,27 +2204,7 @@
 			return 0;
 
 		case SIOCSIFMTU:	/* Set the MTU of a device */
-			if (ifr->ifr_mtu == dev->mtu)
-				return 0;
-
-			/*
-			 *	MTU must be positive.
-			 */
-			if (ifr->ifr_mtu < 0)
-				return -EINVAL;
-
-			if (!netif_device_present(dev))
-				return -ENODEV;
-
-			err = 0;
-			if (dev->change_mtu)
-				err = dev->change_mtu(dev, ifr->ifr_mtu);
-			else
-				dev->mtu = ifr->ifr_mtu;
-			if (!err && dev->flags & IFF_UP)
-				notifier_call_chain(&netdev_chain,
-						    NETDEV_CHANGEMTU, dev);
-			return err;
+			return dev_set_mtu(dev, ifr->ifr_mtu);
 
 		case SIOCGIFHWADDR:
 			memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
@@ -2310,6 +2292,7 @@
 				return -EEXIST;
 			memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
 			dev->name[IFNAMSIZ - 1] = 0;
+			snprintf(dev->class_dev.class_id, BUS_ID_SIZE, dev->name);
 			notifier_call_chain(&netdev_chain,
 					    NETDEV_CHANGENAME, dev);
 			return 0;
@@ -2436,11 +2419,9 @@
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
 			dev_load(ifr.ifr_name);
-			dev_probe_lock();
 			rtnl_lock();
 			ret = dev_ifsioc(&ifr, cmd);
 			rtnl_unlock();
-			dev_probe_unlock();
 			if (!ret) {
 				if (colon)
 					*colon = ':';
@@ -2477,11 +2458,9 @@
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
 			dev_load(ifr.ifr_name);
-			dev_probe_lock();
 			rtnl_lock();
 			ret = dev_ifsioc(&ifr, cmd);
 			rtnl_unlock();
-			dev_probe_unlock();
 			return ret;
 
 		case SIOCGIFMEM:
@@ -2501,11 +2480,9 @@
 			    (cmd >= SIOCDEVPRIVATE &&
 			     cmd <= SIOCDEVPRIVATE + 15)) {
 				dev_load(ifr.ifr_name);
-				dev_probe_lock();
 				rtnl_lock();
 				ret = dev_ifsioc(&ifr, cmd);
 				rtnl_unlock();
-				dev_probe_unlock();
 				if (!ret && copy_to_user(arg, &ifr,
 							 sizeof(struct ifreq)))
 					ret = -EFAULT;
@@ -2582,6 +2559,7 @@
 	int ret;
 
 	BUG_ON(dev_boot_phase);
+	ASSERT_RTNL();
 
 	spin_lock_init(&dev->queue_lock);
 	spin_lock_init(&dev->xmit_lock);
@@ -2590,11 +2568,9 @@
 	dev->fastpath_lock = RW_LOCK_UNLOCKED;
 #endif
 
-#ifdef CONFIG_NET_DIVERT
 	ret = alloc_divert_blk(dev);
 	if (ret)
 		goto out;
-#endif /* CONFIG_NET_DIVERT */
 
 	dev->iflink = -1;
 
@@ -2613,11 +2589,10 @@
 		if (d == dev || !strcmp(d->name, dev->name))
 			goto out_err;
 	}
-	snprintf(dev->kobj.name,KOBJ_NAME_LEN,dev->name);
-	kobj_set_kset_s(dev,net_subsys);
-	if ((ret = kobject_register(&dev->kobj)))
-		goto out_err;
 	
+	if ((ret = netdev_register_sysfs(dev)))
+	    goto out_err;
+
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
 	    !(dev->features & (NETIF_F_IP_CSUM |
@@ -2654,15 +2629,13 @@
 	/* Notify protocols, that a new device appeared. */
 	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
 
-	net_run_sbin_hotplug(dev, "register");
+	net_run_sbin_hotplug(dev, 1);
 	ret = 0;
 
 out:
 	return ret;
 out_err:
-#ifdef CONFIG_NET_DIVERT
 	free_divert_blk(dev);
-#endif
 	goto out;
 }
 
@@ -2673,7 +2646,7 @@
  *	Destroy and free a dead device. A value of zero is returned on
  *	success.
  */
-int netdev_finish_unregister(struct net_device *dev)
+static int netdev_finish_unregister(struct net_device *dev)
 {
 	BUG_TRAP(!dev->ip_ptr);
 	BUG_TRAP(!dev->ip6_ptr);
@@ -2688,11 +2661,109 @@
 	printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name,
 	       (dev->destructor != NULL)?"":", old style");
 #endif
+
+	/* It must be the very last action, after this 'dev' may point
+	 * to freed up memory.
+	 */
 	if (dev->destructor)
 		dev->destructor(dev);
+
 	return 0;
 }
 
+static void netdev_wait_allrefs(struct net_device *dev)
+{
+	unsigned long rebroadcast_time, warning_time;
+
+	rebroadcast_time = warning_time = jiffies;
+	while (atomic_read(&dev->refcnt) != 0) {
+		if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
+			rtnl_shlock();
+			rtnl_exlock();
+
+			/* Rebroadcast unregister notification */
+			notifier_call_chain(&netdev_chain,
+					    NETDEV_UNREGISTER, dev);
+
+			if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
+				     &dev->state)) {
+				/* We must not have linkwatch events
+				 * pending on unregister. If this
+				 * happens, we simply run the queue
+				 * unscheduled, resulting in a noop
+				 * for this device.
+				 */
+				linkwatch_run_queue();
+			}
+
+			rtnl_exunlock();
+			rtnl_shunlock();
+
+			rebroadcast_time = jiffies;
+		}
+
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(HZ / 4);
+		current->state = TASK_RUNNING;
+
+		if (time_after(jiffies, warning_time + 10 * HZ)) {
+			printk(KERN_EMERG "unregister_netdevice: "
+			       "waiting for %s to become free. Usage "
+			       "count = %d\n",
+			       dev->name, atomic_read(&dev->refcnt));
+			warning_time = jiffies;
+		}
+	}
+}
+
+/* The sequence is:
+ *
+ *	rtnl_lock();
+ *	...
+ *	register_netdevice(x1);
+ *	register_netdevice(x2);
+ *	...
+ *	unregister_netdevice(y1);
+ *	unregister_netdevice(y2);
+ *      ...
+ *	rtnl_unlock();
+ *
+ * We are invoked by rtnl_unlock() after it drops the semaphore.
+ * This allows us to deal with two problems:
+ * 1) We can invoke hotplug without deadlocking with linkwatch via
+ *    keventd.
+ * 2) Since we run with the RTNL semaphore not held, we can sleep
+ *    safely in order to wait for the netdev refcnt to drop to zero.
+ */
+static spinlock_t unregister_todo_lock = SPIN_LOCK_UNLOCKED;
+static struct net_device *unregister_todo;
+
+void netdev_run_todo(void)
+{
+	struct net_device *dev;
+
+	net_run_hotplug_todo();
+
+	spin_lock(&unregister_todo_lock);
+	dev = unregister_todo;
+	unregister_todo = NULL;
+	spin_unlock(&unregister_todo_lock);
+
+	while (dev) {
+		struct net_device *next = dev->next;
+
+		dev->next = NULL;
+
+		netdev_wait_allrefs(dev);
+
+		BUG_ON(atomic_read(&dev->refcnt));
+
+		netdev_finish_unregister(dev);
+
+		dev = next;
+	}
+}
+
 /* Synchronize with packet receive processing. */
 void synchronize_net(void) 
 {
@@ -2715,10 +2786,10 @@
 
 int unregister_netdevice(struct net_device *dev)
 {
-	unsigned long now, warning_time;
 	struct net_device *d, **dp;
 
 	BUG_ON(dev_boot_phase);
+	ASSERT_RTNL();
 
 	/* If device is running, close it first. */
 	if (dev->flags & IFF_UP)
@@ -2751,7 +2822,7 @@
 	/* Shutdown queueing discipline. */
 	dev_shutdown(dev);
 
-	net_run_sbin_hotplug(dev, "unregister");
+	net_run_sbin_hotplug(dev, 0);
 	
 	/* Notify protocols, that we are about to destroy
 	   this device. They should clean all the things.
@@ -2769,81 +2840,15 @@
 	/* Notifier chain MUST detach us from master device. */
 	BUG_TRAP(!dev->master);
 
-#ifdef CONFIG_NET_DIVERT
 	free_divert_blk(dev);
-#endif
-
-	if (dev->destructor != NULL) {
-#ifdef NET_REFCNT_DEBUG
-		if (atomic_read(&dev->refcnt) != 1)
-			printk(KERN_DEBUG "unregister_netdevice: holding %s "
-					  "refcnt=%d\n",
-			       dev->name, atomic_read(&dev->refcnt) - 1);
-#endif
-		goto out;
-	}
-
-	/* Last reference is our one */
-	if (atomic_read(&dev->refcnt) == 1)
-		goto out;
 
-#ifdef NET_REFCNT_DEBUG
-	printk(KERN_DEBUG "unregister_netdevice: waiting %s refcnt=%d\n",
-	       dev->name, atomic_read(&dev->refcnt));
-#endif
-
-	/* EXPLANATION. If dev->refcnt is not now 1 (our own reference)
-	   it means that someone in the kernel still has a reference
-	   to this device and we cannot release it.
-
-	   "New style" devices have destructors, hence we can return from this
-	   function and destructor will do all the work later. As of kernel
-	   2.4.0 there are very few "New Style" devices.
-
-	   "Old style" devices expect that the device is free of any references
-	   upon exit from this function.
-	   We cannot return from this function until all such references have
-	   fallen away. This is because the caller of this function will
-	   probably immediately kfree(*dev) and then be unloaded via
-	   sys_delete_module.
+	netdev_unregister_sysfs(dev);
 
-	   So, we linger until all references fall away.  The duration of the
-	   linger is basically unbounded! It is driven by, for example, the
-	   current setting of sysctl_ipfrag_time.
-
-	   After 1 second, we start to rebroadcast unregister notifications
-	   in hope that careless clients will release the device.
-
-	 */
-
-	now = warning_time = jiffies;
-	while (atomic_read(&dev->refcnt) != 1) {
-		if ((jiffies - now) > 1 * HZ) {
-			/* Rebroadcast unregister notification */
-			notifier_call_chain(&netdev_chain,
-					    NETDEV_UNREGISTER, dev);
+	spin_lock(&unregister_todo_lock);
+	dev->next = unregister_todo;
+	unregister_todo = dev;
+	spin_unlock(&unregister_todo_lock);
 
-			if (test_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
-				/* We must not have linkwatch events pending
-				 * on unregister. If this happens, we simply
-				 * run the queue unscheduled, resulting in a
-				 * noop for this device
-				 */
-				linkwatch_run_queue();
-			}
-		}
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ / 4);
-		current->state = TASK_RUNNING;
-		if ((jiffies - warning_time) > 10 * HZ) {
-			printk(KERN_EMERG "unregister_netdevice: waiting for "
-			       "%s to become free. Usage count = %d\n",
-			       dev->name, atomic_read(&dev->refcnt));
-			warning_time = jiffies;
-		}
-	}
-out:
-	kobject_unregister(&dev->kobj);
 	dev_put(dev);
 	return 0;
 }
@@ -2862,8 +2867,6 @@
 extern void dv_init(void);
 #endif /* CONFIG_NET_DIVERT */
 
-static decl_subsys(net,NULL,NULL);
-
 
 /*
  *       This is called single threaded during boot, so no need
@@ -2879,7 +2882,8 @@
 	if (dev_proc_init())
 		goto out;
 
-	subsystem_register(&net_subsys);
+	if (netdev_sysfs_init())
+		goto out;
 
 	INIT_LIST_HEAD(&ptype_all);
 	for (i = 0; i < 16; i++) 
@@ -2953,7 +2957,8 @@
 		 */
 		netdev_boot_setup_check(dev);
 
-		if (dev->init && dev->init(dev)) {
+		if ( (dev->init && dev->init(dev)) ||
+		     netdev_register_sysfs(dev) ) {
 			/*
 			 * It failed to come up. It will be unhooked later.
 			 * dev_alloc_name can now advance to next suitable
@@ -3013,18 +3018,22 @@
 
 #ifdef CONFIG_HOTPLUG
 
-/* Notify userspace when a netdevice event occurs,
- * by running '/sbin/hotplug net' with certain
- * environment variables set.
- */
+struct net_hotplug_todo {
+	struct net_hotplug_todo	*next;
+	char			ifname[IFNAMSIZ];
+	int			is_register;
+};
+static spinlock_t net_hotplug_list_lock = SPIN_LOCK_UNLOCKED;
+static struct net_hotplug_todo *net_hotplug_list;
 
-static int net_run_sbin_hotplug(struct net_device *dev, char *action)
+static void net_run_hotplug_one(struct net_hotplug_todo *ent)
 {
 	char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32];
 	int i;
 
-	sprintf(ifname, "INTERFACE=%s", dev->name);
-	sprintf(action_str, "ACTION=%s", action);
+	sprintf(ifname, "INTERFACE=%s", ent->ifname);
+	sprintf(action_str, "ACTION=%s",
+		(ent->is_register ? "register" : "unregister"));
 
         i = 0;
         argv[i++] = hotplug_path;
@@ -3039,6 +3048,46 @@
 	envp [i++] = action_str;
 	envp [i] = 0;
 
-	return call_usermodehelper(argv [0], argv, envp, 0);
+	call_usermodehelper(argv [0], argv, envp, 0);
+}
+
+static void net_run_hotplug_todo(void)
+{
+	struct net_hotplug_todo *list;
+
+	spin_lock(&net_hotplug_list_lock);
+	list = net_hotplug_list;
+	net_hotplug_list = NULL;
+	spin_unlock(&net_hotplug_list_lock);
+
+	while (list != NULL) {
+		struct net_hotplug_todo *next = list->next;
+
+		net_run_hotplug_one(list);
+
+		kfree(list);
+		list = next;
+	}
+}
+
+/* Notify userspace when a netdevice event occurs,
+ * by running '/sbin/hotplug net' with certain
+ * environment variables set.
+ */
+
+static void net_run_sbin_hotplug(struct net_device *dev, int is_register)
+{
+	struct net_hotplug_todo *ent = kmalloc(sizeof(*ent), GFP_KERNEL);
+
+	if (!ent)
+		return;
+
+	memcpy(ent->ifname, dev->name, IFNAMSIZ);
+	ent->is_register = is_register;
+
+	spin_lock(&net_hotplug_list_lock);
+	ent->next = net_hotplug_list;
+	net_hotplug_list = ent;
+	spin_unlock(&net_hotplug_list_lock);
 }
 #endif
diff -urN linux-2.5.69-bk14/net/core/dst.c linux-2.5.69-bk15/net/core/dst.c
--- linux-2.5.69-bk14/net/core/dst.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk15/net/core/dst.c	2003-05-21 04:47:36.000000000 -0700
@@ -226,7 +226,6 @@
 				   _race_ _condition_.
 				 */
 				if (event!=NETDEV_DOWN &&
-				    dev->destructor == NULL &&
 				    dst->output == dst_blackhole) {
 					dst->dev = &loopback_dev;
 					dev_put(dev);
diff -urN linux-2.5.69-bk14/net/core/link_watch.c linux-2.5.69-bk15/net/core/link_watch.c
--- linux-2.5.69-bk14/net/core/link_watch.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/net/core/link_watch.c	2003-05-21 04:47:36.000000000 -0700
@@ -48,7 +48,8 @@
 static struct lw_event singleevent;
 
 /* Must be called with the rtnl semaphore held */
-void linkwatch_run_queue(void) {
+void linkwatch_run_queue(void)
+{
 	LIST_HEAD(head);
 	struct list_head *n, *next;
 
diff -urN linux-2.5.69-bk14/net/core/net-sysfs.c linux-2.5.69-bk15/net/core/net-sysfs.c
--- linux-2.5.69-bk14/net/core/net-sysfs.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk15/net/core/net-sysfs.c	2003-05-21 04:47:36.000000000 -0700
@@ -0,0 +1,344 @@
+/*
+ * net-sysfs.c - network device class and attributes
+ *
+ * Copyright (c) 2003 Stephen Hemminber <shemminger@osdl.org>
+ * 
+ *
+ * TODO:
+ * last_tx
+ * last_rx
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <net/sock.h>
+#include <linux/rtnetlink.h>
+
+const char *if_port_text[] = {
+   [IF_PORT_UNKNOWN] = "unknown",
+   [IF_PORT_10BASE2] = "BNC",
+   [IF_PORT_10BASET] = "10baseT",
+   [IF_PORT_AUI]     = "AUI",
+   [IF_PORT_100BASET] = "100baseT",
+   [IF_PORT_100BASETX] = "100baseTX",
+   [IF_PORT_100BASEFX] = "100baseFX"
+};
+
+#define to_net_dev(class) container_of((class), struct net_device, class_dev)
+
+/* generate a show function for  simple field */
+#define NETDEVICE_SHOW(field, format_string)				\
+static ssize_t show_##field(struct class_device *dev, char *buf)	\
+{									\
+	return sprintf(buf, format_string, to_net_dev(dev)->field);	\
+}
+
+/* generate a store function for a field with locking */
+#define NETDEVICE_STORE(field)						\
+static ssize_t 								\
+store_##field(struct class_device *dev, const char *buf, size_t len)	\
+{									\
+	char *endp;							\
+	long new = simple_strtol(buf, &endp, 16);			\
+									\
+	if (endp == buf || new < 0)					\
+		return -EINVAL;						\
+									\
+	if (!capable(CAP_NET_ADMIN))					\
+		return -EPERM;						\
+									\
+	rtnl_lock();							\
+	to_net_dev(dev)->field = new;					\
+	rtnl_unlock();							\
+	return len;							\
+}
+
+/* generate a read-only network device class attribute */
+#define NETDEVICE_ATTR(field, format_string)				\
+NETDEVICE_SHOW(field, format_string)					\
+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)		\
+
+NETDEVICE_ATTR(addr_len, "%d\n");
+NETDEVICE_ATTR(iflink, "%d\n");
+NETDEVICE_ATTR(ifindex, "%d\n");
+NETDEVICE_ATTR(features, "%#x\n");
+NETDEVICE_ATTR(type, "%d\n");
+
+/* TODO: only a few devices set this now should fix others. */
+static ssize_t show_port(struct class_device *dev, char *buf)
+{
+	unsigned char port = to_net_dev(dev)->if_port;
+	char *cp = buf;
+
+	cp += sprintf(cp, "%d", port);
+	if (port < ARRAY_SIZE(if_port_text))
+		cp += sprintf(cp, " (%s)", if_port_text[port]);
+	*cp++ ='\n';
+	return cp - buf;
+}
+static CLASS_DEVICE_ATTR(if_port, S_IRUGO, show_port, NULL);
+
+static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
+{
+	int i;
+	char *cp = buf;
+
+	read_lock(&dev_base_lock);
+	for (i = 0; i < len; i++)
+		cp += sprintf(cp, "%02x%c", addr[i],
+			      i == (len - 1) ? '\n' : ':');
+	read_unlock(&dev_base_lock);
+	return cp - buf;
+}
+
+static ssize_t show_address(struct class_device *dev, char *buf)
+{
+	struct net_device *net = to_net_dev(dev);
+	return format_addr(buf, net->dev_addr, net->addr_len);
+}
+
+static ssize_t show_broadcast(struct class_device *dev, char *buf)
+{
+	struct net_device *net = to_net_dev(dev);
+	return format_addr(buf, net->broadcast, net->addr_len);
+}
+
+static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL);
+
+/* read-write attributes */
+NETDEVICE_SHOW(mtu, "%d\n");
+
+static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
+{
+	char *endp;
+	int new_mtu;
+	int err;
+
+	new_mtu = simple_strtoul(buf, &endp, 10);
+	if (endp == buf) 
+		return -EINVAL;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+	
+	rtnl_lock();
+	err = dev_set_mtu(to_net_dev(dev), new_mtu);
+	rtnl_unlock();
+
+	return err == 0 ? len : err;
+}
+
+static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
+
+NETDEVICE_SHOW(flags, "%#x\n");
+
+static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
+{
+	unsigned long new_flags;
+	char *endp;
+	int err = 0;
+
+	new_flags = simple_strtoul(buf, &endp, 16);
+	if (endp == buf)
+		return -EINVAL;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+	
+	rtnl_lock();
+	err = dev_change_flags(to_net_dev(dev), new_flags);
+	rtnl_unlock();
+
+	return err ? err : len;
+}
+
+static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
+
+NETDEVICE_SHOW(tx_queue_len, "%lu\n");
+NETDEVICE_STORE(tx_queue_len);
+static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, 
+			 store_tx_queue_len);
+
+static struct class net_class = {
+	.name = "net",
+};
+
+
+static struct class_device_attribute *net_class_attributes[] = {
+	&class_device_attr_ifindex,
+	&class_device_attr_iflink,
+	&class_device_attr_addr_len,
+	&class_device_attr_tx_queue_len,
+	&class_device_attr_features,
+	&class_device_attr_mtu,
+	&class_device_attr_flags,
+	&class_device_attr_if_port,
+	&class_device_attr_type,
+	&class_device_attr_address,
+	&class_device_attr_broadcast,
+	NULL
+};
+
+struct netstat_fs_entry {
+	struct attribute attr;
+	ssize_t (*show)(const struct net_device_stats *, char *);
+	ssize_t (*store)(struct net_device_stats *, const char *, size_t);
+};
+
+static ssize_t net_device_stat_show(unsigned long var, char *buf)
+{
+	return sprintf(buf, "%ld\n", var);
+}
+
+/* generate a read-only statistics attribute */
+#define NETDEVICE_STAT(_NAME)						\
+static ssize_t show_stat_##_NAME(const struct net_device_stats *stats,	\
+				 char *buf)				\
+{									\
+	return net_device_stat_show(stats->_NAME, buf);			\
+}									\
+static struct netstat_fs_entry net_stat_##_NAME  = {		   	\
+	.attr = {.name = __stringify(_NAME), .mode = S_IRUGO },		\
+	.show = show_stat_##_NAME,					\
+}
+
+NETDEVICE_STAT(rx_packets);
+NETDEVICE_STAT(tx_packets);
+NETDEVICE_STAT(rx_bytes);
+NETDEVICE_STAT(tx_bytes);
+NETDEVICE_STAT(rx_errors);
+NETDEVICE_STAT(tx_errors);
+NETDEVICE_STAT(rx_dropped);
+NETDEVICE_STAT(tx_dropped);
+NETDEVICE_STAT(multicast);
+NETDEVICE_STAT(collisions);
+NETDEVICE_STAT(rx_length_errors);
+NETDEVICE_STAT(rx_over_errors);
+NETDEVICE_STAT(rx_crc_errors);
+NETDEVICE_STAT(rx_frame_errors);
+NETDEVICE_STAT(rx_fifo_errors);
+NETDEVICE_STAT(rx_missed_errors);
+NETDEVICE_STAT(tx_aborted_errors);
+NETDEVICE_STAT(tx_carrier_errors);
+NETDEVICE_STAT(tx_fifo_errors);
+NETDEVICE_STAT(tx_heartbeat_errors);
+NETDEVICE_STAT(tx_window_errors);
+NETDEVICE_STAT(rx_compressed);
+NETDEVICE_STAT(tx_compressed);
+
+static struct attribute *default_attrs[] = {
+	&net_stat_rx_packets.attr,
+	&net_stat_tx_packets.attr,
+	&net_stat_rx_bytes.attr,
+	&net_stat_tx_bytes.attr,
+	&net_stat_rx_errors.attr,
+	&net_stat_tx_errors.attr,
+	&net_stat_rx_dropped.attr,
+	&net_stat_tx_dropped.attr,
+	&net_stat_multicast.attr,
+	&net_stat_collisions.attr,
+	&net_stat_rx_length_errors.attr,
+	&net_stat_rx_over_errors.attr,
+	&net_stat_rx_crc_errors.attr,
+	&net_stat_rx_frame_errors.attr,
+	&net_stat_rx_fifo_errors.attr,
+	&net_stat_rx_missed_errors.attr,
+	&net_stat_tx_aborted_errors.attr,
+	&net_stat_tx_carrier_errors.attr,
+	&net_stat_tx_fifo_errors.attr,
+	&net_stat_tx_heartbeat_errors.attr,
+	&net_stat_tx_window_errors.attr,
+	&net_stat_rx_compressed.attr,
+	&net_stat_tx_compressed.attr,
+	NULL
+};
+
+
+static ssize_t
+netstat_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct netstat_fs_entry *entry
+		= container_of(attr, struct netstat_fs_entry, attr);
+	struct class_device *class_dev
+		= container_of(kobj->parent, struct class_device, kobj);
+	struct net_device *dev
+		= to_net_dev(class_dev);
+	struct net_device_stats *stats 
+		= dev->get_stats ? dev->get_stats(dev) : NULL;
+
+	if (stats && entry->show) 
+		return entry->show(stats, buf);
+	return -EINVAL;
+}
+
+static struct sysfs_ops netstat_sysfs_ops = {
+	.show = netstat_attr_show,
+};
+
+static struct kobj_type netstat_ktype = {
+	.sysfs_ops	= &netstat_sysfs_ops,
+	.default_attrs  = default_attrs,
+};
+
+/* Create sysfs entries for network device. */
+int netdev_register_sysfs(struct net_device *net)
+{
+	struct class_device *class_dev = &(net->class_dev);
+	int i;
+	struct class_device_attribute *attr;
+	int ret;
+
+	memset(class_dev, 0, sizeof(struct class_device)); 
+	class_dev->class = &net_class;
+	class_dev->dev = net->dev;
+	class_dev->class_data = net;
+
+	snprintf(class_dev->class_id, BUS_ID_SIZE, net->name);
+	if ((ret = class_device_register(class_dev)))
+		goto out;
+
+	for (i = 0; (attr = net_class_attributes[i]); i++) {
+		if ((ret = class_device_create_file(class_dev, attr)))
+		    goto out_unreg;
+	}
+
+	if (net->get_stats) {
+		struct kobject *k = &net->stats_kobj;
+
+		memset(k, 0, sizeof(*k));
+		k->parent = kobject_get(&class_dev->kobj);
+		if (!k->parent) {
+			ret = -EBUSY;
+			goto out_unreg;
+		}
+
+		snprintf(k->name, KOBJ_NAME_LEN, "%s", "statistics");
+		k->ktype = &netstat_ktype;
+
+		if((ret = kobject_register(k))) 
+			 goto out_unreg; 
+	}
+
+out:
+	return ret;
+out_unreg:
+	printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n",
+	       net->name, ret);
+	class_device_unregister(class_dev);
+	goto out;
+}
+
+void netdev_unregister_sysfs(struct net_device *net)
+{
+	if (net->get_stats)
+		kobject_del(&net->stats_kobj);
+	class_device_unregister(&net->class_dev);
+}
+
+int netdev_sysfs_init(void)
+{
+	return class_register(&net_class);
+}
diff -urN linux-2.5.69-bk14/net/core/rtnetlink.c linux-2.5.69-bk15/net/core/rtnetlink.c
--- linux-2.5.69-bk14/net/core/rtnetlink.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/core/rtnetlink.c	2003-05-21 04:47:36.000000000 -0700
@@ -52,7 +52,7 @@
 
 DECLARE_MUTEX(rtnl_sem);
 
-void rtnl_lock(void)
+void rtnl_lock()
 {
 	rtnl_shlock();
 	rtnl_exlock();
@@ -62,6 +62,8 @@
 {
 	rtnl_exunlock();
 	rtnl_shunlock();
+
+	netdev_run_todo();
 }
 
 int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
@@ -500,6 +502,8 @@
 		}
 
 		up(&rtnl_sem);
+
+		netdev_run_todo();
 	} while (rtnl && rtnl->receive_queue.qlen);
 }
 
diff -urN linux-2.5.69-bk14/net/decnet/dn_dev.c linux-2.5.69-bk15/net/decnet/dn_dev.c
--- linux-2.5.69-bk14/net/decnet/dn_dev.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/decnet/dn_dev.c	2003-05-21 04:47:36.000000000 -0700
@@ -273,7 +273,7 @@
 
 	memcpy(t, &dn_dev_sysctl, sizeof(*t));
 
-	for(i = 0; i < (sizeof(t->dn_dev_vars)/sizeof(t->dn_dev_vars[0]) - 1); i++) {
+	for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
 		long offset = (long)t->dn_dev_vars[i].data;
 		t->dn_dev_vars[i].data = ((char *)parms) + offset;
 		t->dn_dev_vars[i].de = NULL;
diff -urN linux-2.5.69-bk14/net/ipv4/devinet.c linux-2.5.69-bk15/net/ipv4/devinet.c
--- linux-2.5.69-bk14/net/ipv4/devinet.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv4/devinet.c	2003-05-21 04:47:36.000000000 -0700
@@ -552,7 +552,6 @@
 		goto out;
 	}
 
-	dev_probe_lock();
 	rtnl_lock();
 
 	ret = -ENODEV;
@@ -702,12 +701,10 @@
 	}
 done:
 	rtnl_unlock();
-	dev_probe_unlock();
 out:
 	return ret;
 rarok:
 	rtnl_unlock();
-	dev_probe_unlock();
 	ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
 	goto out;
 }
@@ -1305,9 +1302,7 @@
 	if (!t)
 		return;
 	memcpy(t, &devinet_sysctl, sizeof(*t));
-	for (i = 0;
-	     i < sizeof(t->devinet_vars) / sizeof(t->devinet_vars[0]) - 1;
-	     i++) {
+	for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
 		t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
 		t->devinet_vars[i].de = NULL;
 	}
diff -urN linux-2.5.69-bk14/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.5.69-bk15/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.5.69-bk14/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-05-21 04:47:36.000000000 -0700
@@ -301,7 +301,7 @@
 	array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
 	array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF;
 
-	for (i = 0; i < sizeof(search) / sizeof(search[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(search); i++) {
 		if (search[i].dir != dir) continue;
 
 		found = find_pattern(ftp_buffer, skb->len - dataoff,
diff -urN linux-2.5.69-bk14/net/ipv4/route.c linux-2.5.69-bk15/net/ipv4/route.c
--- linux-2.5.69-bk14/net/ipv4/route.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv4/route.c	2003-05-21 04:47:36.000000000 -0700
@@ -958,12 +958,15 @@
  				INIT_RCU_HEAD(&rt->u.dst.rcu_head);
 				rt->u.dst.__use		= 1;
 				atomic_set(&rt->u.dst.__refcnt, 1);
+				rt->u.dst.child		= NULL;
 				if (rt->u.dst.dev)
 					dev_hold(rt->u.dst.dev);
+				rt->u.dst.obsolete	= 0;
 				rt->u.dst.lastuse	= jiffies;
+				rt->u.dst.path		= &rt->u.dst;
 				rt->u.dst.neighbour	= NULL;
 				rt->u.dst.hh		= NULL;
-				rt->u.dst.obsolete	= 0;
+				rt->u.dst.xfrm		= NULL;
 
 				rt->rt_flags		|= RTCF_REDIRECTED;
 
@@ -1150,7 +1153,7 @@
 {
 	int i;
 	
-	for (i = 0; i < sizeof(mtu_plateau) / sizeof(mtu_plateau[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(mtu_plateau); i++)
 		if (old_mtu > mtu_plateau[i])
 			return mtu_plateau[i];
 	return 68;
diff -urN linux-2.5.69-bk14/net/ipv4/syncookies.c linux-2.5.69-bk15/net/ipv4/syncookies.c
--- linux-2.5.69-bk14/net/ipv4/syncookies.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv4/syncookies.c	2003-05-21 04:47:36.000000000 -0700
@@ -17,6 +17,7 @@
 #include <linux/tcp.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/kernel.h>
 #include <net/tcp.h>
 
 extern int sysctl_tcp_syncookies;
@@ -38,7 +39,7 @@
 	(__u16)-1
 };
 /* The number doesn't include the -1 terminator */
-#define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1)
+#define NUM_MSS (ARRAY_SIZE(msstab) - 1)
 
 /*
  * Generate a syncookie.  mssp points to the mss, which is returned
diff -urN linux-2.5.69-bk14/net/ipv4/tcp_diag.c linux-2.5.69-bk15/net/ipv4/tcp_diag.c
--- linux-2.5.69-bk14/net/ipv4/tcp_diag.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv4/tcp_diag.c	2003-05-21 04:47:36.000000000 -0700
@@ -613,7 +613,7 @@
 		if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
 			return;
 		err = tcpdiag_rcv_msg(skb, nlh);
-		if (err) 
+		if (err || nlh->nlmsg_flags & NLM_F_ACK) 
 			netlink_ack(skb, nlh, err);
 	}
 }
diff -urN linux-2.5.69-bk14/net/ipv6/addrconf.c linux-2.5.69-bk15/net/ipv6/addrconf.c
--- linux-2.5.69-bk14/net/ipv6/addrconf.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/addrconf.c	2003-05-21 04:47:36.000000000 -0700
@@ -1140,7 +1140,7 @@
 	 *
 	 *  - Reserved subnet anycast (RFC 2526)
 	 *	11111101 11....11 1xxxxxxx
-	 *  - ISATAP (draft-ietf-ngtrans-isatap-01.txt) 4.3
+	 *  - ISATAP (draft-ietf-ngtrans-isatap-13.txt) 5.1
 	 *	00-00-5E-FE-xx-xx-xx-xx
 	 *  - value 0
 	 *  - XXX: already assigned to an address on the device
diff -urN linux-2.5.69-bk14/net/ipv6/ah6.c linux-2.5.69-bk15/net/ipv6/ah6.c
--- linux-2.5.69-bk14/net/ipv6/ah6.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/ah6.c	2003-05-21 04:47:36.000000000 -0700
@@ -36,17 +36,6 @@
 #include <net/xfrm.h>
 #include <asm/scatterlist.h>
 
-/* XXX no ipv6 ah specific */
-#define NIP6(addr) \
-	ntohs((addr).s6_addr16[0]),\
-	ntohs((addr).s6_addr16[1]),\
-	ntohs((addr).s6_addr16[2]),\
-	ntohs((addr).s6_addr16[3]),\
-	ntohs((addr).s6_addr16[4]),\
-	ntohs((addr).s6_addr16[5]),\
-	ntohs((addr).s6_addr16[6]),\
-	ntohs((addr).s6_addr16[7])
-
 int ah6_output(struct sk_buff *skb)
 {
 	int err;
diff -urN linux-2.5.69-bk14/net/ipv6/esp6.c linux-2.5.69-bk15/net/ipv6/esp6.c
--- linux-2.5.69-bk14/net/ipv6/esp6.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/esp6.c	2003-05-21 04:47:36.000000000 -0700
@@ -46,17 +46,6 @@
 /* Move to common area: it is shared with AH. */
 /* Common with AH after some work on arguments. */
 
-/* XXX no ipv6 esp specific */
-#define NIP6(addr) \
-	ntohs((addr).s6_addr16[0]),\
-	ntohs((addr).s6_addr16[1]),\
-	ntohs((addr).s6_addr16[2]),\
-	ntohs((addr).s6_addr16[3]),\
-	ntohs((addr).s6_addr16[4]),\
-	ntohs((addr).s6_addr16[5]),\
-	ntohs((addr).s6_addr16[6]),\
-	ntohs((addr).s6_addr16[7])
-
 static int get_offset(u8 *packet, u32 packet_len, u8 *nexthdr, struct ipv6_opt_hdr **prevhdr)
 {
 	u16 offset = sizeof(struct ipv6hdr);
diff -urN linux-2.5.69-bk14/net/ipv6/exthdrs.c linux-2.5.69-bk15/net/ipv6/exthdrs.c
--- linux-2.5.69-bk14/net/ipv6/exthdrs.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/exthdrs.c	2003-05-21 04:47:36.000000000 -0700
@@ -405,7 +405,7 @@
   Hop-by-hop options.
  **********************************/
 
-/* Router Alert as of draft-ietf-ipngwg-ipv6router-alert-04 */
+/* Router Alert as of RFC 2711 */
 
 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
 {
@@ -684,7 +684,7 @@
 /*
  * Skip any extension headers. This is used by the ICMP module.
  *
- * Note that strictly speaking this conflicts with RFC1883 4.0:
+ * Note that strictly speaking this conflicts with RFC 2460 4.0:
  * ...The contents and semantics of each extension header determine whether 
  * or not to proceed to the next header.  Therefore, extension headers must
  * be processed strictly in the order they appear in the packet; a
diff -urN linux-2.5.69-bk14/net/ipv6/icmp.c linux-2.5.69-bk15/net/ipv6/icmp.c
--- linux-2.5.69-bk14/net/ipv6/icmp.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/icmp.c	2003-05-21 04:47:36.000000000 -0700
@@ -557,22 +557,7 @@
 				    skb_checksum(skb, 0, skb->len, 0))) {
 			if (net_ratelimit())
 				printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
-				       ntohs(saddr->s6_addr16[0]),
-				       ntohs(saddr->s6_addr16[1]),
-				       ntohs(saddr->s6_addr16[2]),
-				       ntohs(saddr->s6_addr16[3]),
-				       ntohs(saddr->s6_addr16[4]),
-				       ntohs(saddr->s6_addr16[5]),
-				       ntohs(saddr->s6_addr16[6]),
-				       ntohs(saddr->s6_addr16[7]),
-				       ntohs(daddr->s6_addr16[0]),
-				       ntohs(daddr->s6_addr16[1]),
-				       ntohs(daddr->s6_addr16[2]),
-				       ntohs(daddr->s6_addr16[3]),
-				       ntohs(daddr->s6_addr16[4]),
-				       ntohs(daddr->s6_addr16[5]),
-				       ntohs(daddr->s6_addr16[6]),
-				       ntohs(daddr->s6_addr16[7]));
+				       NIP6(*saddr), NIP6(*daddr));
 			goto discard_it;
 		}
 	}
diff -urN linux-2.5.69-bk14/net/ipv6/ipcomp6.c linux-2.5.69-bk15/net/ipv6/ipcomp6.c
--- linux-2.5.69-bk14/net/ipv6/ipcomp6.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/ipcomp6.c	2003-05-21 04:47:36.000000000 -0700
@@ -44,17 +44,6 @@
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
 
-/* XXX no ipv6 ipcomp specific */
-#define NIP6(addr) \
-	ntohs((addr).s6_addr16[0]),\
-	ntohs((addr).s6_addr16[1]),\
-	ntohs((addr).s6_addr16[2]),\
-	ntohs((addr).s6_addr16[3]),\
-	ntohs((addr).s6_addr16[4]),\
-	ntohs((addr).s6_addr16[5]),\
-	ntohs((addr).s6_addr16[6]),\
-	ntohs((addr).s6_addr16[7])
-
 static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	int err = 0;
diff -urN linux-2.5.69-bk14/net/ipv6/mcast.c linux-2.5.69-bk15/net/ipv6/mcast.c
--- linux-2.5.69-bk14/net/ipv6/mcast.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/mcast.c	2003-05-21 04:47:36.000000000 -0700
@@ -20,7 +20,7 @@
  *	yoshfuji	: fix format of router-alert option
  *	YOSHIFUJI Hideaki @USAGI:
  *		Fixed source address for MLD message based on
- *		<draft-ietf-magma-mld-source-02.txt>.
+ *		<draft-ietf-magma-mld-source-05.txt>.
  *	YOSHIFUJI Hideaki @USAGI:
  *		- Ignore Queries for invalid addresses.
  *		- MLD for link-local addresses.
@@ -1227,7 +1227,7 @@
 	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
-		/* <draft-ietf-magma-mld-source-02.txt>:
+		/* <draft-ietf-magma-mld-source-05.txt>:
 		 * use unspecified address as the source address 
 		 * when a valid link-local address is not available.
 		 */
@@ -1559,7 +1559,7 @@
 	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
-		/* <draft-ietf-magma-mld-source-02.txt>:
+		/* <draft-ietf-magma-mld-source-05.txt>:
 		 * use unspecified address as the source address 
 		 * when a valid link-local address is not available.
 		 */
diff -urN linux-2.5.69-bk14/net/ipv6/netfilter/ip6t_LOG.c linux-2.5.69-bk15/net/ipv6/netfilter/ip6t_LOG.c
--- linux-2.5.69-bk14/net/ipv6/netfilter/ip6t_LOG.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/netfilter/ip6t_LOG.c	2003-05-21 04:47:36.000000000 -0700
@@ -25,16 +25,6 @@
 #define DEBUGP(format, args...)
 #endif
 
-#define NIP6(addr) \
-	ntohs((addr).s6_addr16[0]), \
-	ntohs((addr).s6_addr16[1]), \
-	ntohs((addr).s6_addr16[2]), \
-	ntohs((addr).s6_addr16[3]), \
-	ntohs((addr).s6_addr16[4]), \
-	ntohs((addr).s6_addr16[5]), \
-	ntohs((addr).s6_addr16[6]), \
-	ntohs((addr).s6_addr16[7])
-
 struct esphdr {
 	__u32   spi;
 }; /* FIXME evil kludge */
diff -urN linux-2.5.69-bk14/net/ipv6/proc.c linux-2.5.69-bk15/net/ipv6/proc.c
--- linux-2.5.69-bk14/net/ipv6/proc.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/proc.c	2003-05-21 04:47:36.000000000 -0700
@@ -67,7 +67,7 @@
 #define SNMP6_SENTINEL	{ .name = NULL, .offset = 0 }
 
 static struct snmp6_item snmp6_ipv6_list[] = {
-/* ipv6 mib according to draft-ietf-ipngwg-ipv6-mib-04 */
+/* ipv6 mib according to RFC 2465 */
 #define SNMP6_GEN(x) { .name = #x , .offset = offsetof(struct ipv6_mib, x) }
 	SNMP6_GEN(Ip6InReceives),
 	SNMP6_GEN(Ip6InHdrErrors),
@@ -96,7 +96,7 @@
 };
 
 static struct snmp6_item snmp6_icmp6_list[] = {
-/* icmpv6 mib according to draft-ietf-ipngwg-ipv6-icmp-mib-02
+/* icmpv6 mib according to RFC 2466
 
    Exceptions:  {In|Out}AdminProhibs are removed, because I see
                 no good reasons to account them separately
diff -urN linux-2.5.69-bk14/net/ipv6/route.c linux-2.5.69-bk15/net/ipv6/route.c
--- linux-2.5.69-bk14/net/ipv6/route.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/route.c	2003-05-21 04:47:36.000000000 -0700
@@ -912,7 +912,7 @@
 		goto out;
 
 	/*
-	 *	RFC 1970 specifies that redirects should only be
+	 *	RFC 2461 specifies that redirects should only be
 	 *	accepted if they come from the nexthop to the target.
 	 *	Due to the way default routers are chosen, this notion
 	 *	is a bit fuzzy and one might need to check all default
diff -urN linux-2.5.69-bk14/net/ipv6/sit.c linux-2.5.69-bk15/net/ipv6/sit.c
--- linux-2.5.69-bk14/net/ipv6/sit.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/sit.c	2003-05-21 04:47:36.000000000 -0700
@@ -420,7 +420,7 @@
 }
 
 /* Returns the embedded IPv4 address if the IPv6 address
-   comes from 6to4 (draft-ietf-ngtrans-6to4-04) addr space */
+   comes from 6to4 (RFC 3056) addr space */
 
 static inline u32 try_6to4(struct in6_addr *v6dst)
 {
diff -urN linux-2.5.69-bk14/net/ipv6/udp.c linux-2.5.69-bk15/net/ipv6/udp.c
--- linux-2.5.69-bk14/net/ipv6/udp.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/ipv6/udp.c	2003-05-21 04:47:36.000000000 -0700
@@ -666,7 +666,7 @@
 		goto short_packet;
 
 	if (uh->check == 0) {
-		/* IPv6 draft-v2 section 8.1 says that we SHOULD log
+		/* RFC 2460 section 8.1 says that we SHOULD log
 		   this error. Well, it is reasonable.
 		 */
 		if (net_ratelimit())
diff -urN linux-2.5.69-bk14/net/irda/irproc.c linux-2.5.69-bk15/net/irda/irproc.c
--- linux-2.5.69-bk14/net/irda/irproc.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk15/net/irda/irproc.c	2003-05-21 04:47:36.000000000 -0700
@@ -53,8 +53,6 @@
 	{"irias",	irias_proc_read},
 };
 
-#define IRDA_ENTRIES_NUM (sizeof(dir)/sizeof(dir[0]))
- 
 /*
  * Function irda_proc_register (void)
  *
@@ -70,7 +68,7 @@
 		return;
 	proc_irda->owner = THIS_MODULE;
 
-	for (i=0;i<IRDA_ENTRIES_NUM;i++)
+	for (i=0; i<ARRAY_SIZE(dir); i++)
 		create_proc_info_entry(dir[i].name,0,proc_irda,dir[i].fn);
 }
 
@@ -85,7 +83,7 @@
 	int i;
 
         if (proc_irda) {
-                for (i=0;i<IRDA_ENTRIES_NUM;i++)
+                for (i=0; i<ARRAY_SIZE(dir); i++)
                         remove_proc_entry(dir[i].name, proc_irda);
 
                 remove_proc_entry("net/irda", NULL);
diff -urN linux-2.5.69-bk14/net/netlink/netlink_dev.c linux-2.5.69-bk15/net/netlink/netlink_dev.c
--- linux-2.5.69-bk14/net/netlink/netlink_dev.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/netlink/netlink_dev.c	2003-05-21 04:47:36.000000000 -0700
@@ -232,7 +232,7 @@
 	devfs_mk_dir("netlink");
 
 	/*  Someone tell me the official names for the uppercase ones  */
-	for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(entries); i++) {
 		devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor),
 			S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name);
 	}
@@ -259,7 +259,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(entries); i++)
 		devfs_remove("netlink/%s", entries[i].name);
 	for (i = 0; i < 16; i++)
 		devfs_remove("netlink/tap%d", i);
diff -urN linux-2.5.69-bk14/net/netsyms.c linux-2.5.69-bk15/net/netsyms.c
--- linux-2.5.69-bk14/net/netsyms.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/netsyms.c	2003-05-21 04:47:36.000000000 -0700
@@ -82,8 +82,6 @@
 
 #endif
 
-extern int netdev_finish_unregister(struct net_device *dev);
-
 #include <linux/rtnetlink.h>
 
 #ifdef CONFIG_IPX_MODULE
@@ -562,7 +560,6 @@
 EXPORT_SYMBOL(dev_get_by_name);
 EXPORT_SYMBOL(__dev_get_by_name);
 EXPORT_SYMBOL(dev_getbyhwaddr);
-EXPORT_SYMBOL(netdev_finish_unregister);
 EXPORT_SYMBOL(netdev_set_master);
 EXPORT_SYMBOL(eth_type_trans);
 #ifdef CONFIG_FDDI
diff -urN linux-2.5.69-bk14/net/sctp/ipv6.c linux-2.5.69-bk15/net/sctp/ipv6.c
--- linux-2.5.69-bk14/net/sctp/ipv6.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/sctp/ipv6.c	2003-05-21 04:47:36.000000000 -0700
@@ -77,17 +77,6 @@
 
 extern struct notifier_block sctp_inetaddr_notifier;
 
-/* FIXME: This macro needs to be moved to a common header file. */
-#define NIP6(addr) \
-        ntohs((addr)->s6_addr16[0]), \
-        ntohs((addr)->s6_addr16[1]), \
-        ntohs((addr)->s6_addr16[2]), \
-        ntohs((addr)->s6_addr16[3]), \
-        ntohs((addr)->s6_addr16[4]), \
-        ntohs((addr)->s6_addr16[5]), \
-        ntohs((addr)->s6_addr16[6]), \
-        ntohs((addr)->s6_addr16[7])
-
 /* ICMP error handler. */
 void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 		 int type, int code, int offset, __u32 info)
@@ -180,8 +169,8 @@
 	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
 			  "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
 			  "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-			  __FUNCTION__, skb, skb->len, NIP6(fl.fl6_src),
-			  NIP6(fl.fl6_dst));
+			  __FUNCTION__, skb, skb->len, 
+			  NIP6(*fl.fl6_src), NIP6(*fl.fl6_dst));
 
 	SCTP_INC_STATS(SctpOutSCTPPacks);
 
@@ -200,13 +189,13 @@
 		.nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } };
 
 	SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
-			  __FUNCTION__, NIP6(fl.fl6_dst));
+			  __FUNCTION__, NIP6(*fl.fl6_dst));
 
 	if (saddr) {
 		fl.fl6_src = &saddr->v6.sin6_addr;
 		SCTP_DEBUG_PRINTK(
 			"SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ",
-			NIP6(fl.fl6_src));
+			NIP6(*fl.fl6_src));
 	}
 
 	dst = ip6_route_output(NULL, &fl);
@@ -216,7 +205,7 @@
 		SCTP_DEBUG_PRINTK(
 			"rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
 			"rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-			NIP6(&rt->rt6i_dst.addr), NIP6(&rt->rt6i_src.addr));
+			NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
 	} else {
 		SCTP_DEBUG_PRINTK("NO ROUTE\n");
 	}
@@ -263,13 +252,13 @@
 
 	SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
 			  "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
-			  __FUNCTION__, asoc, dst, NIP6(&daddr->v6.sin6_addr));
+			  __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
 
 	if (!asoc) {
 		ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
 		SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: "
 				  "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-				  NIP6(&saddr->v6.sin6_addr));
+				  NIP6(saddr->v6.sin6_addr));
 		return;
 	}
 
@@ -298,12 +287,12 @@
 		memcpy(saddr, baddr, sizeof(union sctp_addr));
 		SCTP_DEBUG_PRINTK("saddr: "
 				  "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-				  NIP6(&saddr->v6.sin6_addr));
+				  NIP6(saddr->v6.sin6_addr));
 	} else {
 		printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
 		       "address for the "
 		       "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-		       __FUNCTION__, asoc, NIP6(&daddr->v6.sin6_addr));
+		       __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
 	}
 
 	sctp_read_unlock(addr_lock);
diff -urN linux-2.5.69-bk14/net/sctp/objcnt.c linux-2.5.69-bk15/net/sctp/objcnt.c
--- linux-2.5.69-bk14/net/sctp/objcnt.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/sctp/objcnt.c	2003-05-21 04:47:36.000000000 -0700
@@ -38,6 +38,7 @@
  * be incorporated into the next SCTP release.
  */
 
+#include <linux/kernel.h>
 #include <net/sctp/sctp.h>
 
 /*
@@ -88,7 +89,7 @@
 	char temp[128];
 
 	/* How many entries? */
-	entries = sizeof(sctp_dbg_objcnt)/sizeof(sctp_dbg_objcnt[0]);
+	entries = ARRAY_SIZE(sctp_dbg_objcnt);
 
 	/* Walk the entries and print out the debug information
 	 * for proc fs.
diff -urN linux-2.5.69-bk14/net/socket.c linux-2.5.69-bk15/net/socket.c
--- linux-2.5.69-bk14/net/socket.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/socket.c	2003-05-21 04:47:36.000000000 -0700
@@ -821,11 +821,7 @@
 		case SIOCGIFDIVERT:
 		case SIOCSIFDIVERT:
 		/* Convert this to call through a hook */
-#ifdef CONFIG_NET_DIVERT
 			err = divert_ioctl(cmd, (struct divert_cf *)arg);
-#else
-			err = -ENOPKG;
-#endif	/* CONFIG_NET_DIVERT */
 			break;
 		case SIOCADDDLCI:
 		case SIOCDELDLCI:
diff -urN linux-2.5.69-bk14/net/sunrpc/pmap_clnt.c linux-2.5.69-bk15/net/sunrpc/pmap_clnt.c
--- linux-2.5.69-bk14/net/sunrpc/pmap_clnt.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk15/net/sunrpc/pmap_clnt.c	2003-05-21 04:47:36.000000000 -0700
@@ -288,7 +288,7 @@
 struct rpc_program	pmap_program = {
 	.name		= "portmap",
 	.number		= RPC_PMAP_PROGRAM,
-	.nrvers		= sizeof(pmap_version)/sizeof(pmap_version[0]),
+	.nrvers		= ARRAY_SIZE(pmap_version),
 	.version	= pmap_version,
 	.stats		= &pmap_stats,
 };
diff -urN linux-2.5.69-bk14/net/sunrpc/svcsock.c linux-2.5.69-bk15/net/sunrpc/svcsock.c
--- linux-2.5.69-bk14/net/sunrpc/svcsock.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk15/net/sunrpc/svcsock.c	2003-05-21 04:47:36.000000000 -0700
@@ -35,6 +35,7 @@
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <net/ip.h>
+#include <net/tcp.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
@@ -116,6 +117,22 @@
 }
 
 /*
+ * Any space to write?
+ */
+static inline unsigned long
+svc_sock_wspace(struct svc_sock *svsk)
+{
+	int wspace;
+
+	if (svsk->sk_sock->type == SOCK_STREAM)
+		wspace = tcp_wspace(svsk->sk_sk);
+	else
+		wspace = sock_wspace(svsk->sk_sk);
+
+	return wspace;
+}
+
+/*
  * Queue up a socket with data pending. If there are idle nfsd
  * processes, wake 'em up.
  *
@@ -149,16 +166,18 @@
 		goto out_unlock;
 	}
 
+	set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
 	if (((svsk->sk_reserved + serv->sv_bufsz)*2
-	     > sock_wspace(svsk->sk_sk))
+	     > svc_sock_wspace(svsk))
 	    && !test_bit(SK_CLOSE, &svsk->sk_flags)
 	    && !test_bit(SK_CONN, &svsk->sk_flags)) {
 		/* Don't enqueue while not enough space for reply */
 		dprintk("svc: socket %p  no space, %d*2 > %ld, not enqueued\n",
 			svsk->sk_sk, svsk->sk_reserved+serv->sv_bufsz,
-			sock_wspace(svsk->sk_sk));
+			svc_sock_wspace(svsk));
 		goto out_unlock;
 	}
+	clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
 
 	/* Mark socket as busy. It will remain in this state until the
 	 * server has processed all pending data and put the socket back
@@ -341,9 +360,6 @@
 
 	slen = xdr->len;
 
-	/* Grab svsk->sk_sem to serialize outgoing data. */
-	down(&svsk->sk_sem);
-
 	if (rqstp->rq_prot == IPPROTO_UDP) {
 		/* set the destination */
 		struct msghdr	msg;
@@ -396,8 +412,6 @@
 			len += result;
 	}
 out:
-	up(&svsk->sk_sem);
-
 	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n",
 			rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
 		rqstp->rq_addr.sin_addr.s_addr);
@@ -886,8 +900,12 @@
 			goto error;
 		svsk->sk_tcplen += len;
 
-		if (len < want)
-			return 0;
+		if (len < want) {
+			dprintk("svc: short recvfrom while reading record length (%d of %lu)\n",
+			        len, want);
+			svc_sock_received(svsk);
+			return -EAGAIN; /* record header not complete */
+		}
 
 		svsk->sk_reclen = ntohl(svsk->sk_reclen);
 		if (!(svsk->sk_reclen & 0x80000000)) {
@@ -1011,6 +1029,7 @@
 svc_tcp_init(struct svc_sock *svsk)
 {
 	struct sock	*sk = svsk->sk_sk;
+	struct tcp_opt  *tp = tcp_sk(sk);
 
 	svsk->sk_recvfrom = svc_tcp_recvfrom;
 	svsk->sk_sendto = svc_tcp_sendto;
@@ -1028,6 +1047,8 @@
 		svsk->sk_reclen = 0;
 		svsk->sk_tcplen = 0;
 
+		tp->nonagle = 1;        /* disable Nagle's algorithm */
+
 		/* initialise setting must have enough space to
 		 * receive and respond to one request.  
 		 * svc_tcp_recvfrom will re-adjust if necessary
@@ -1232,7 +1253,13 @@
 		xb->page_len +
 		xb->tail[0].iov_len;
 
-	len = svsk->sk_sendto(rqstp);
+	/* Grab svsk->sk_sem to serialize outgoing data. */
+	down(&svsk->sk_sem);
+	if (test_bit(SK_DEAD, &svsk->sk_flags))
+		len = -ENOTCONN;
+	else
+		len = svsk->sk_sendto(rqstp);
+	up(&svsk->sk_sem);
 	svc_sock_release(rqstp);
 
 	if (len == -ECONNREFUSED || len == -ENOTCONN || len == -EAGAIN)
diff -urN linux-2.5.69-bk14/net/wanrouter/wanproc.c linux-2.5.69-bk15/net/wanrouter/wanproc.c
--- linux-2.5.69-bk14/net/wanrouter/wanproc.c	2003-05-21 04:47:25.000000000 -0700
+++ linux-2.5.69-bk15/net/wanrouter/wanproc.c	2003-05-21 04:47:37.000000000 -0700
@@ -4,7 +4,7 @@
 *		This module is completely hardware-independent and provides
 *		access to the router using Linux /proc filesystem.
 *
-* Author: 	Gideon Hack	
+* Author: 	Gideon Hack
 *
 * Copyright:	(c) 1995-1999 Sangoma Technologies Inc.
 *
@@ -20,22 +20,17 @@
 * Dec 13, 1996	Gene Kozin	Initial version (based on Sangoma's WANPIPE)
 *****************************************************************************/
 
-#include <linux/version.h>
 #include <linux/config.h>
+#include <linux/init.h>		/* __initfunc et al. */
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/mm.h>		/* verify_area(), etc. */
-#include <linux/string.h>	/* inline mem*, str* functions */
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <asm/io.h>
 #include <linux/wanrouter.h>	/* WAN router API definitions */
 #include <linux/seq_file.h>
 #include <linux/smp_lock.h>
-#include <linux/init.h>	/* __initfunc et al. */
-#include <asm/uaccess.h>       /* copy_to_user */
+
+#include <asm/io.h>
 
 #define PROC_STATS_FORMAT "%30s: %12lu\n"
 
@@ -47,16 +42,6 @@
 				    (prot == WANCONFIG_CHDLC) ? " CHDLC": \
 				       (prot == WANCONFIG_MPPP) ? " MPPP" : \
 				           " Unknown" )
-	
-/****** Data Types **********************************************************/
-
-typedef struct wan_stat_entry
-{
-	struct wan_stat_entry *next;
-	char *description;		/* description string */
-	void *data;			/* -> data */
-	unsigned data_type;		/* data type */
-} wan_stat_entry_t;
 
 /****** Function Prototypes *************************************************/
 
@@ -74,11 +59,11 @@
  */
 
 /*
- *	Generic /proc/net/router/<file> file and inode operations 
+ *	Generic /proc/net/router/<file> file and inode operations
  */
 
 /*
- *	/proc/net/router 
+ *	/proc/net/router
  */
 
 static struct proc_dir_entry *proc_router;
@@ -106,12 +91,14 @@
 		;
 	return wandev;
 }
+
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct wan_device *wandev = v;
 	(*pos)++;
 	return (v == (void *)1) ? router_devlist : wandev->next;
 }
+
 static void r_stop(struct seq_file *m, void *v)
 {
 	unlock_kernel();
@@ -121,8 +108,8 @@
 {
 	struct wan_device *p = v;
 	if (v == (void *)1) {
-		seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |");
-		seq_puts(m, "mem.size|option1|option2|option3|option4\n");
+		seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |"
+			    "mem.size|option1|option2|option3|option4\n");
 		return 0;
 	}
 	if (!p->state)
@@ -137,21 +124,21 @@
 {
 	struct wan_device *p = v;
 	if (v == (void *)1) {
-		seq_puts(m, "Device name    |protocol|station|interface|");
-		seq_puts(m, "clocking|baud rate| MTU |ndev|link state\n");
+		seq_puts(m, "Device name    |protocol|station|interface|"
+			    "clocking|baud rate| MTU |ndev|link state\n");
 		return 0;
 	}
 	if (!p->state)
 		return 0;
-	seq_printf(m, "%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
+	seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
 		p->name,
 		PROT_DECODE(p->config_id),
-		p->config_id == WANCONFIG_FR ? 
-			(p->station ? " Node" : " CPE") :
+		p->config_id == WANCONFIG_FR ?
+			(p->station ? "Node" : "CPE") :
 			(p->config_id == WANCONFIG_X25 ?
-			(p->station ? " DCE" : " DTE") :
-			(" N/A")),
-		p->interface ? " V.35" : " RS-232",
+			(p->station ? "DCE" : "DTE") :
+			("N/A")),
+		p->interface ? "V.35" : "RS-232",
 		p->clocking ? "internal" : "external",
 		p->bps,
 		p->mtu,
@@ -178,17 +165,17 @@
 }
 
 static struct seq_operations config_op = {
-	.start =r_start,
-	.next =	r_next,
-	.stop =	r_stop,
-	.show =	config_show
+	.start	= r_start,
+	.next	= r_next,
+	.stop	= r_stop,
+	.show	= config_show,
 };
 
 static struct seq_operations status_op = {
-	.start =r_start,
-	.next =	r_next,
-	.stop =	r_stop,
-	.show =	status_show
+	.start	= r_start,
+	.next	= r_next,
+	.stop	= r_stop,
+	.show	= status_show,
 };
 
 static int config_open(struct inode *inode, struct file *file)
@@ -201,22 +188,20 @@
 	return seq_open(file, &status_op);
 }
 
-static struct file_operations config_fops =
-{
-	.owner =	THIS_MODULE,
-	.open =		config_open,
-	.read =		seq_read,
-	.llseek =	seq_lseek,
-	.release =	seq_release,
+static struct file_operations config_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = config_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release,
 };
 
-static struct file_operations status_fops =
-{
-	.owner =	THIS_MODULE,
-	.open =		status_open,
-	.read =		seq_read,
-	.llseek =	seq_lseek,
-	.release =	seq_release,
+static struct file_operations status_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = status_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release,
 };
 
 static int wandev_show(struct seq_file *m, void *v)
@@ -235,11 +220,11 @@
 	if (wandev->update) {
 		int err = wandev->update(wandev);
 		if (err == -EAGAIN) {
-			seq_printf(m, "Device is busy!\n");
+			seq_puts(m, "Device is busy!\n");
 			return 0;
 		}
 		if (err) {
-			seq_printf(m, "Device is not configured!\n");
+			seq_puts(m, "Device is not configured!\n");
 			return 0;
 		}
 	}
@@ -286,21 +271,20 @@
 	return single_open(file, wandev_show, PDE(inode)->data);
 }
 
-static struct file_operations wandev_fops =
-{
-	.owner =	THIS_MODULE,
-	.open =		wandev_open,
-	.read =		seq_read,
-	.llseek =	seq_lseek,
-	.release =	single_release,
-	.ioctl =	wanrouter_ioctl,
+static struct file_operations wandev_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = wandev_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+	.ioctl	 = wanrouter_ioctl,
 };
 
 /*
  *	Initialize router proc interface.
  */
 
-int __init wanrouter_proc_init (void)
+int __init wanrouter_proc_init(void)
 {
 	struct proc_dir_entry *p;
 	proc_router = proc_mkdir(ROUTER_NAME, proc_net);
@@ -328,11 +312,11 @@
  *	Clean up router proc interface.
  */
 
-void wanrouter_proc_cleanup (void)
+void wanrouter_proc_cleanup(void)
 {
 	remove_proc_entry("config", proc_router);
 	remove_proc_entry("status", proc_router);
-	remove_proc_entry(ROUTER_NAME,proc_net);
+	remove_proc_entry(ROUTER_NAME, proc_net);
 }
 
 /*
@@ -343,7 +327,7 @@
 {
 	if (wandev->magic != ROUTER_MAGIC)
 		return -EINVAL;
-		
+
 	wandev->dent = create_proc_entry(wandev->name, S_IRUGO, proc_router);
 	if (!wandev->dent)
 		return -ENOMEM;
@@ -355,7 +339,6 @@
 /*
  *	Delete directory entry for WAN device.
  */
- 
 int wanrouter_proc_delete(struct wan_device* wandev)
 {
 	if (wandev->magic != ROUTER_MAGIC)
diff -urN linux-2.5.69-bk14/net/xfrm/xfrm_algo.c linux-2.5.69-bk15/net/xfrm/xfrm_algo.c
--- linux-2.5.69-bk14/net/xfrm/xfrm_algo.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk15/net/xfrm/xfrm_algo.c	2003-05-21 04:47:37.000000000 -0700
@@ -251,17 +251,17 @@
 
 static inline int aalg_entries(void)
 {
-	return sizeof(aalg_list) / sizeof(aalg_list[0]);
+	return ARRAY_SIZE(aalg_list);
 }
 
 static inline int ealg_entries(void)
 {
-	return sizeof(ealg_list) / sizeof(ealg_list[0]);
+	return ARRAY_SIZE(ealg_list);
 }
 
 static inline int calg_entries(void)
 {
-	return sizeof(calg_list) / sizeof(calg_list[0]);
+	return ARRAY_SIZE(calg_list);
 }
 
 /* Todo: generic iterators */
diff -urN linux-2.5.69-bk14/sound/core/memalloc.c linux-2.5.69-bk15/sound/core/memalloc.c
--- linux-2.5.69-bk14/sound/core/memalloc.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk15/sound/core/memalloc.c	2003-05-21 04:47:37.000000000 -0700
@@ -27,6 +27,7 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <asm/semaphore.h>
 #include <sound/memalloc.h>
 
