## 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 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, ®s, 0, NULL, NULL); + int pid; + pid = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 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(®s, 0, sizeof(struct pt_regs)); - p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 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(®s, 0, sizeof(struct pt_regs)); - p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 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(®s->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 #include #include #include @@ -60,12 +55,20 @@ #include #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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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. \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 /* request_region(), release_region() */ #include /* WAN router definitions */ #include /* cyclomx common user API definitions */ -#include /* kernel <-> user copy */ #include /* __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 " ""; -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 /* 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; idescriptor.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 /* -#define DEBUG 1 -#define DEBUG_PACKET 1 +#define DEBUG +#define VERBOSE_DEBUG */ #include -#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 " @@ -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 #include #include +#include #include #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 #include #include +#include #include -#include #include +#include #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;ifi_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 #include #include +#include #include #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 #include +#include #include 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//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 + +#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 #include #include -#include +#include #include #include @@ -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 -#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 #include + #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 + * + * + * TODO: + * last_tx + * last_rx + */ + +#include +#include +#include +#include +#include +#include + +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 #include #include +#include #include 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 #include -/* 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 #include -/* 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 - * . + * . * YOSHIFUJI Hideaki @USAGI: * - Ignore Queries for invalid addresses. * - MLD for link-local addresses. @@ -1227,7 +1227,7 @@ } if (ipv6_get_lladdr(dev, &addr_buf)) { - /* : + /* : * 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)) { - /* : + /* : * 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 #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 #include /* @@ -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 #include #include +#include #include #include @@ -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 #include +#include /* __initfunc et al. */ #include /* offsetof(), etc. */ #include /* return codes */ #include #include -#include /* kmalloc(), kfree() */ -#include /* verify_area(), etc. */ -#include /* inline mem*, str* functions */ -#include /* htons(), etc. */ -#include #include /* WAN router API definitions */ #include #include -#include /* __initfunc et al. */ -#include /* copy_to_user */ + +#include #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 and inode operations + * Generic /proc/net/router/ 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 #include #include +#include #include #include