From 93316d043b53967917e0f593727e6d06634ed656 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:33:25 -0500 Subject: [PATCH] Import 2.3.99pre3-6 --- CREDITS | 10 + Documentation/Configure.help | 13 +- MAINTAINERS | 8 +- Makefile | 2 +- arch/sparc/Makefile | 2 +- arch/sparc64/Makefile | 4 +- arch/sparc64/kernel/Makefile | 4 +- arch/sparc64/kernel/ioctl32.c | 18 +- arch/sparc64/kernel/sys_sparc32.c | 15 +- drivers/atm/Makefile | 28 +- drivers/atm/ambassador.c | 551 +++++++++++++---------- drivers/atm/ambassador.h | 22 +- drivers/atm/atmdev_init.c | 2 +- drivers/atm/atmtcp.c | 61 ++- drivers/atm/eni.c | 271 ++++++----- drivers/atm/eni.h | 3 + drivers/atm/fore200e.c | 174 ++++--- drivers/atm/fore200e.h | 32 +- drivers/atm/horizon.c | 124 ++--- drivers/atm/horizon.h | 2 - drivers/atm/idt77105.c | 64 ++- drivers/atm/iphase.c | 161 +++---- drivers/atm/nicstar.c | 141 +++--- drivers/atm/nicstar.h | 2 - drivers/atm/suni.c | 169 ++++--- drivers/atm/suni.h | 4 +- drivers/atm/uPD98402.c | 123 +++-- drivers/atm/zatm.c | 26 +- drivers/char/atixlmouse.c | 2 +- drivers/char/busmouse.c | 21 - drivers/char/busmouse.h | 2 - drivers/char/misc.c | 3 - drivers/ieee1394/Config.in | 3 +- drivers/ieee1394/csr.c | 168 ++++--- drivers/ieee1394/csr.h | 1 - drivers/ieee1394/highlevel.c | 61 +-- drivers/ieee1394/highlevel.h | 41 +- drivers/ieee1394/ieee1394.h | 99 ++++ drivers/ieee1394/ieee1394_core.c | 161 +++---- drivers/ieee1394/ieee1394_core.h | 17 +- drivers/ieee1394/ieee1394_transactions.c | 37 +- drivers/ieee1394/ieee1394_types.h | 3 + drivers/ieee1394/ohci1394.c | 195 +++++--- drivers/ieee1394/ohci1394.h | 35 +- drivers/ieee1394/pcilynx.c | 78 +++- drivers/ieee1394/pcilynx.h | 119 ++--- drivers/ieee1394/raw1394.c | 161 +++++-- drivers/ieee1394/raw1394.h | 7 +- drivers/sbus/char/sunmouse.c | 15 +- drivers/sbus/char/sunserial.c | 4 +- drivers/scsi/qlogicisp.c | 1 + drivers/sound/sb_card.c.rej | 290 ------------ drivers/video/cgthreefb.c | 10 +- fs/nfs/flushd.c | 1 + fs/nfs/write.c | 1 + fs/pipe.c | 2 +- include/asm-sparc/asm_offsets.h | 60 +-- include/asm-sparc/pgtable.h | 11 +- include/asm-sparc64/page.h | 5 +- include/linux/atm_idt77105.h | 14 +- include/linux/atm_suni.h | 11 +- include/linux/atmdev.h | 143 ++++-- include/linux/netdevice.h | 3 + include/linux/nfs_fs.h | 1 + include/linux/sonet.h | 45 +- kernel/exit.c | 2 +- net/atm/Makefile | 9 +- net/atm/addr.c | 54 +-- net/atm/addr.h | 3 +- net/atm/atm_misc.c | 28 +- net/atm/clip.c | 13 +- net/atm/common.c | 181 +++++--- net/atm/ipcommon.c | 26 +- net/atm/ipcommon.h | 6 +- net/atm/lane_mpoa_init.c | 12 + net/atm/lec.c | 80 ++-- net/atm/lec.h | 8 + net/atm/mpc.c | 8 +- net/atm/proc.c | 15 +- net/atm/pvc.c | 9 +- net/atm/raw.c | 22 +- net/atm/resources.c | 14 +- net/atm/signaling.c | 42 +- net/atm/signaling.h | 1 - net/atm/svc.c | 170 ++++--- net/bridge/br.c | 18 +- net/bridge/br_input.c | 8 +- net/bridge/br_private.h | 4 +- net/core/dev.c | 2 +- net/ipv4/ipip.c | 2 +- net/ipv4/netfilter/ip_queue.c | 2 +- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/sit.c | 2 +- net/sched/sch_atm.c | 25 +- 95 files changed, 2624 insertions(+), 2013 deletions(-) delete mode 100644 drivers/sound/sb_card.c.rej diff --git a/CREDITS b/CREDITS index 4fa4ef90bf4d..fe323fbfbc8c 100644 --- a/CREDITS +++ b/CREDITS @@ -1961,6 +1961,16 @@ S: Lazarettstrasse 8 S: 91054 Erlangen S: Germany +N: Giuliano Procida +E: myxie@debian.org,gprocida@madge.com +D: Madge Ambassador driver (Collage 155 Server ATM adapter) +D: Madge Horizon driver (Collage 25 and 155 Client ATM adapters) +P: 1024/93898735 D3 9E F4 F7 6D 8D 2F 3A 38 BA 06 7C 2B 33 43 7D +S: Madge Networks +S: Framewood Road +S: Wexham SL3 6PJ +S: United Kingdom + N: Daniel Quinlan E: quinlan@pathname.com W: http://www.pathname.com/~quinlan/ diff --git a/Documentation/Configure.help b/Documentation/Configure.help index bcf2d831ec2f..ec5703e89c07 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -13297,7 +13297,7 @@ CONFIG_IEEE1394_OHCI1394 say M here and read Documentation/modules.txt. The module will be called ohci1394.o. -RAW IEEE 1394 I/O support +Raw IEEE 1394 I/O support CONFIG_IEEE1394_RAWIO Say Y here if you want support for the raw device. This is generally a good idea, so you should say Y here. The raw device enables @@ -13308,6 +13308,17 @@ CONFIG_IEEE1394_RAWIO say M here and read Documentation/modules.txt. The module will be called raw1394.o. +Excessive debugging output +CONFIG_IEEE1394_VERBOSEDEBUG + If you say Y here, you will get very verbose debugging logs from the + subsystem which includes a dump of the header of every sent and + received packet. This can amount to a high amount of data collected + in a very short time which is usually also saved to disk by the + system logging daemons. + + Say Y if you really want or need the debugging output, everyone else + says N. + # # m68k-specific kernel options # Documented by Chris Lawrence et al. diff --git a/MAINTAINERS b/MAINTAINERS index f03fbb625c9e..2a5276f5196e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -495,36 +495,32 @@ S: Maintained IEEE 1394 SUBSYSTEM P: Andreas Bombe M: andreas.bombe@munich.netsurf.de -L: linux1394-devel@eclipt.uni-klu.ac.at -W: http://eclipt.uni-klu.ac.at/ieee1394 +L: linux1394-devel@lists.sourceforge.net +W: http://linux1394.sourceforge.net/ S: Maintained IEEE 1394 AIC5800 DRIVER P: Emanuel Pirker M: epirker@edu.uni-klu.ac.at L: linux1394-devel@eclipt.uni-klu.ac.at -W: http://eclipt.uni-klu.ac.at/ieee1394 S: Maintained IEEE 1394 OHCI DRIVER P: Sebastien Rougeaux M: sebastien.rougeaux@anu.edu.au L: linux1394-devel@eclipt.uni-klu.ac.at -W: http://eclipt.uni-klu.ac.at/ieee1394 S: Maintained IEEE 1394 PCILYNX DRIVER P: Andreas Bombe M: andreas.bombe@munich.netsurf.de L: linux1394-devel@eclipt.uni-klu.ac.at -W: http://eclipt.uni-klu.ac.at/ieee1394 S: Maintained IEEE 1394 RAW I/O DRIVER P: Andreas Bombe M: andreas.bombe@munich.netsurf.de L: linux1394-devel@eclipt.uni-klu.ac.at -W: http://eclipt.uni-klu.ac.at/ieee1394 S: Maintained INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT diff --git a/Makefile b/Makefile index 8e6a0f0efe64..184c30b82c2c 100644 --- a/Makefile +++ b/Makefile @@ -146,7 +146,7 @@ DRIVERS-$(CONFIG_APPLETALK) += drivers/net/appletalk/appletalk.a DRIVERS-$(CONFIG_TR) += drivers/net/tokenring/tr.a DRIVERS-$(CONFIG_WAN) += drivers/net/wan/wan.a DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnet.a -DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.a +DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o DRIVERS-$(CONFIG_IDE) += drivers/ide/ide.a DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsi.a DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394.a diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 6725e8cfe12d..2fe7a2c1854f 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.45 2000/01/29 01:08:48 anton Exp $ +# $Id: Makefile,v 1.46 2000/03/21 06:12:26 davem Exp $ # sparc/Makefile # # Makefile for the architecture dependent flags and dependencies on the diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index 868dd685152c..585fa4a3b551 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.42 2000/03/09 05:56:43 jj Exp $ +# $Id: Makefile,v 1.43 2000/03/21 06:12:28 davem Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -18,6 +18,8 @@ NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null > NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; ) +export NEW_GCC + ifneq ($(NEW_GAS),y) AS = sparc64-linux-as LD = sparc64-linux-ld diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index f06ece6823e7..124776f51f4e 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.51 2000/02/08 05:11:31 jj Exp $ +# $Id: Makefile,v 1.52 2000/03/19 07:00:29 ecd Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -61,7 +61,7 @@ head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \ # binfmt_elf32.o: $(TOPDIR)/fs/binfmt_elf.c -ifneq ($(IS_EGCS),y) +ifneq ($(NEW_GCC),y) CMODEL_CFLAG := -mmedlow else CMODEL_CFLAG := -mcmodel=medlow diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 0ba88adf66a6..92aa5f6ad638 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.83 2000/03/14 07:31:25 jj Exp $ +/* $Id: ioctl32.c,v 1.84 2000/03/21 21:19:18 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -1803,6 +1803,8 @@ struct atm_iobuf32 { #define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32) #define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32) #define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) +#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) +#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) static struct { unsigned int cmd32; @@ -1821,7 +1823,9 @@ static struct { { ATM_SETESI32, ATM_SETESI }, { ATM_SETESIF32, ATM_SETESIF }, { ATM_GETSTAT32, ATM_GETSTAT }, - { ATM_GETSTATZ32, ATM_GETSTATZ } + { ATM_GETSTATZ32, ATM_GETSTATZ }, + { ATM_GETLOOP32, ATM_GETLOOP }, + { ATM_SETLOOP32, ATM_SETLOOP } }; #define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0])) @@ -1941,8 +1945,6 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) unsigned int cmd = 0; switch (cmd32) { - case SUNI_GETLOOP: - case SUNI_SETLOOP: case SONET_GETSTAT: case SONET_GETSTATZ: case SONET_GETDIAG: @@ -1954,7 +1956,6 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) return do_atmif_sioc(fd, cmd32, arg); } - if (cmd == 0) { for (i = 0; i < NR_ATM_IOCTL; i++) { if (cmd32 == atm_ioctl_map[i].cmd32) { cmd = atm_ioctl_map[i].cmd; @@ -1964,7 +1965,6 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) if (i == NR_ATM_IOCTL) { return -EINVAL; } - } switch (cmd) { case ATM_GETNAMES: @@ -1983,6 +1983,8 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) case ATM_SETESIF: case ATM_GETSTAT: case ATM_GETSTATZ: + case ATM_GETLOOP: + case ATM_SETLOOP: return do_atmif_sioc(fd, cmd, arg); } @@ -3076,8 +3078,8 @@ HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl) HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl) HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl) HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl) -HANDLE_IOCTL(SUNI_GETLOOP, do_atm_ioctl) -HANDLE_IOCTL(SUNI_SETLOOP, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl) HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl) HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl) HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl) diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 763acdc0f1ab..58b8d3c2bf90 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.139 2000/03/16 20:37:57 davem Exp $ +/* $Id: sys_sparc32.c,v 1.140 2000/03/22 02:44:35 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -3634,7 +3634,7 @@ struct nfsctl_arg32 { union nfsctl_res32 { __u8 cr32_getfh[NFS_FHSIZE]; - u32 cr32_debug; + struct knfsd_fh cr32_getfs; }; static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) @@ -3760,15 +3760,12 @@ static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32 return err; } +/* This really doesn't need translations, we are only passing + * back a union which contains opaque nfs file handle data. + */ static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) { - int err; - - err = copy_to_user(&res32->cr32_getfh, - &kres->cr_getfh, - sizeof(res32->cr32_getfh)); - err |= __put_user(kres->cr_debug, &res32->cr32_debug); - return err; + return copy_to_user(res32, kres, sizeof(*res32)); } extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp); diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile index f126bd232717..8dbf1364aa73 100644 --- a/drivers/atm/Makefile +++ b/drivers/atm/Makefile @@ -3,15 +3,15 @@ # Makefile for the Linux network (ATM) device drivers. # -L_TARGET := atm.a -L_OBJS := atmdev_init.o +O_TARGET := atm.o +O_OBJS := atmdev_init.o M_OBJS := MOD_LIST_NAME := ATM_MODULES include ../../.config ifeq ($(CONFIG_ATM_ENI),y) -L_OBJS += eni.o +O_OBJS += eni.o NEED_SUNI_LX = suni.o else ifeq ($(CONFIG_ATM_ENI),m) @@ -21,8 +21,8 @@ else endif ifeq ($(CONFIG_ATM_ZATM),y) -L_OBJS += zatm.o -LX_OBJS += uPD98402.o +O_OBJS += zatm.o +OX_OBJS += uPD98402.o else ifeq ($(CONFIG_ATM_ZATM),m) M_OBJS += zatm.o @@ -31,11 +31,11 @@ else endif ifeq ($(CONFIG_ATM_TNETA1570),y) -L_OBJS += tneta1570.o suni.o +O_OBJS += tneta1570.o suni.o endif ifeq ($(CONFIG_ATM_NICSTAR),y) -L_OBJS += nicstar.o +O_OBJS += nicstar.o ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y) NEED_SUNI_LX = suni.o endif @@ -55,7 +55,7 @@ else endif ifeq ($(CONFIG_ATM_HORIZON),y) -L_OBJS += horizon.o +O_OBJS += horizon.o else ifeq ($(CONFIG_ATM_HORIZON),m) M_OBJS += horizon.o @@ -63,7 +63,7 @@ else endif ifeq ($(CONFIG_ATM_AMBASSADOR),y) -L_OBJS += ambassador.o +O_OBJS += ambassador.o else ifeq ($(CONFIG_ATM_AMBASSADOR),m) M_OBJS += ambassador.o @@ -71,7 +71,7 @@ else endif ifeq ($(CONFIG_ATM_TCP),y) -L_OBJS += atmtcp.o +O_OBJS += atmtcp.o else ifeq ($(CONFIG_ATM_TCP),m) M_OBJS += atmtcp.o @@ -79,7 +79,7 @@ else endif ifeq ($(CONFIG_ATM_IA),y) -L_OBJS += iphase.o +O_OBJS += iphase.o NEED_SUNI_LX = suni.o else ifeq ($(CONFIG_ATM_IA),m) @@ -91,13 +91,13 @@ endif ifeq ($(NEED_SUNI_LX),) MX_OBJS += $(NEED_SUNI_MX) else - LX_OBJS += $(NEED_SUNI_LX) + OX_OBJS += $(NEED_SUNI_LX) endif ifeq ($(NEED_IDT77105_LX),) MX_OBJS += $(NEED_IDT77105_MX) else - LX_OBJS += $(NEED_IDT77105_LX) + OX_OBJS += $(NEED_IDT77105_LX) endif ifeq ($(CONFIG_ATM_FORE200E_PCA),y) @@ -114,7 +114,7 @@ FORE200E_FW_OBJS += fore200e_sba_fw.o endif endif ifeq ($(CONFIG_ATM_FORE200E),y) -L_OBJS += fore200e.o $(FORE200E_FW_OBJS) +O_OBJS += fore200e.o $(FORE200E_FW_OBJS) else ifeq ($(CONFIG_ATM_FORE200E),m) M_OBJS += fore_200e.o diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 8ec9960c15cc..a71884db7d89 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -39,7 +40,7 @@ #define maintainer_string "Giuliano Procida at Madge Networks " #define description_string "Madge ATM Ambassador driver" -#define version_string "1.2" +#define version_string "1.2.4" static inline void __init show_version (void) { printk ("%s version %s\n", description_string, version_string); @@ -97,8 +98,8 @@ static inline void __init show_version (void) { The adapter is quite intelligent (fast) and has a simple interface (few features). VPI is always zero, 1024 VCIs are supported. There - is limited cell rate support. UBR channels can be kept and ABR - (explicit rate, bu not EFCI) is supported. There is no CBR or VBR + is limited cell rate support. UBR channels can be capped and ABR + (explicit rate, but not EFCI) is supported. There is no CBR or VBR support. 1. Driver <-> Adapter Communication @@ -321,8 +322,29 @@ static unsigned int rxs_bs[NUM_RX_POOLS] = { 4080, 12240, 36720, 65535 }; static unsigned int rx_lats = 7; static unsigned char pci_lat = 0; +static const unsigned long onegigmask = -1 << 30; + /********** access to adapter **********/ +static inline void wr_plain (const amb_dev * dev, const u32 * addr, u32 data) { + PRINTD (DBG_FLOW|DBG_REGS, "wr: %p <- %08x", addr, data); +#ifdef AMB_MMIO + dev->membase[addr - (u32 *) 0] = data; +#else + outl (data, dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); +#endif +} + +static inline u32 rd_plain (const amb_dev * dev, const u32 * addr) { +#ifdef AMB_MMIO + u32 data = dev->membase[addr - (u32 *) 0]; +#else + u32 data = inl (dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); +#endif + PRINTD (DBG_FLOW|DBG_REGS, "rd: %p -> %08x", addr, data); + return data; +} + static const amb_mem * const mem = 0; static inline void wr_mem (const amb_dev * dev, const u32 * addr, u32 data) { @@ -342,7 +364,7 @@ static inline u32 rd_mem (const amb_dev * dev, const u32 * addr) { u32 be = inl (dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); #endif u32 data = be32_to_cpu (be); - PRINTD (DBG_FLOW|DBG_REGS, "rd: %p -> %08x b[%08x]", addr, data, be); + PRINTD (DBG_FLOW|DBG_REGS, "rd: %p -> %08x b[%08x]", addr, data, be); return data; } @@ -350,14 +372,18 @@ static inline u32 rd_mem (const amb_dev * dev, const u32 * addr) { static inline void dump_registers (const amb_dev * dev) { #ifdef DEBUG_AMBASSADOR - // u32 * i; - // PRINTD (DBG_REGS, "mailboxes: "); - // for (i = (u32 *) 0x40; i < (u32 *) 0x60; ++i) - // PRINTD (DBG_REGS, "%08x ", rd_mem (dev, i)); - PRINTD (DBG_REGS, "doorb %08x", rd_mem (dev, (u32 *) 0x60)); - PRINTD (DBG_REGS, "irqev %08x", rd_mem (dev, (u32 *) 0x64)); - PRINTD (DBG_REGS, "irqen %08x", rd_mem (dev, (u32 *) 0x68)); - PRINTD (DBG_REGS, "reset %08x", rd_mem (dev, (u32 *) 0x6c)); + if (debug & DBG_REGS) { + u32 * i; + PRINTD (DBG_REGS, "reading PLX control: "); + for (i = (u32 *) 0x00; i < (u32 *) 0x30; ++i) + rd_mem (dev, i); + PRINTD (DBG_REGS, "reading mailboxes: "); + for (i = (u32 *) 0x40; i < (u32 *) 0x60; ++i) + rd_mem (dev, i); + PRINTD (DBG_REGS, "reading doorb irqev irqen reset:"); + for (i = (u32 *) 0x60; i < (u32 *) 0x70; ++i) + rd_mem (dev, i); + } #else (void) dev; #endif @@ -414,8 +440,8 @@ static inline void dump_skb (char * prefix, unsigned int vc, struct sk_buff * sk static inline int check_area (void * start, size_t length) { // assumes length > 0 - const u32 fourmegmask = (-1)<<22; - const u32 twofivesixmask = (-1)<<8; + const u32 fourmegmask = -1 << 22; + const u32 twofivesixmask = -1 << 8; const u32 starthole = 0xE0000000; u32 startaddress = virt_to_bus (start); u32 lastaddress = startaddress+length-1; @@ -435,7 +461,7 @@ static inline void amb_kfree_skb (struct sk_buff * skb) { if (ATM_SKB(skb)->vcc->pop) { ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb); } else { - dev_kfree_skb (skb); + dev_kfree_skb_any (skb); } } @@ -448,7 +474,7 @@ static inline void tx_complete (amb_dev * dev, tx_out * tx) { PRINTD (DBG_FLOW|DBG_TX, "tx_complete %p %p", dev, tx); // VC layer stats - ATM_SKB(skb)->vcc->stats->tx++; + atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); // free the descriptor kfree (tx_descr); @@ -489,7 +515,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { dump_skb ("<<<", vc, skb); // VC layer stats - atm_vcc->stats->rx++; + atomic_inc(&atm_vcc->stats->rx); skb->stamp = xtime; // end of our responsability atm_vcc->push (atm_vcc, skb); @@ -504,7 +530,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { } else { PRINTK (KERN_INFO, "dropped over-size frame"); // should we count this? - atm_vcc->stats->rx_drop++; + atomic_inc(&atm_vcc->stats->rx_drop); } } else { @@ -524,7 +550,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { dev->stats.rx.unused++; } - dev_kfree_skb (skb); + dev_kfree_skb_any (skb); return; } @@ -548,7 +574,8 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { // sometimes does 16-bit accesses (yuk yuk yuk) static int command_do (amb_dev * dev, command * cmd) { - volatile amb_cq * cq = &dev->cq; + amb_cq * cq = &dev->cq; + volatile amb_cq_ptrs * ptrs = &cq->ptrs; command * my_slot; unsigned long timeout; @@ -562,18 +589,18 @@ static int command_do (amb_dev * dev, command * cmd) { // if not full... if (cq->pending < cq->maximum) { // remember my slot for later - my_slot = cq->in; + my_slot = ptrs->in; PRINTD (DBG_CMD, "command in slot %p", my_slot); dump_command (cmd); // copy command in - *cq->in = *cmd; + *ptrs->in = *cmd; cq->pending++; - cq->in = NEXTQ (cq->in, cq->start, cq->limit); + ptrs->in = NEXTQ (ptrs->in, ptrs->start, ptrs->limit); // mail the command - wr_mem (dev, &mem->mb.adapter.cmd_address, virt_to_bus (cq->in)); + wr_mem (dev, &mem->mb.adapter.cmd_address, virt_to_bus (ptrs->in)); // prepare to wait for cq->pending milliseconds // effectively one centisecond on i386 @@ -591,13 +618,13 @@ static int command_do (amb_dev * dev, command * cmd) { } // wait for my slot to be reached (all waiters are here or above, until...) - while (cq->out != my_slot) { - PRINTD (DBG_CMD, "wait: command slot (now at %p)", cq->out); + while (ptrs->out != my_slot) { + PRINTD (DBG_CMD, "wait: command slot (now at %p)", ptrs->out); schedule(); } // wait on my slot (... one gets to its slot, and... ) - while (cq->out->request != cpu_to_be32 (SRB_COMPLETE)) { + while (ptrs->out->request != cpu_to_be32 (SRB_COMPLETE)) { PRINTD (DBG_CMD, "wait: command slot completion"); schedule(); } @@ -607,12 +634,13 @@ static int command_do (amb_dev * dev, command * cmd) { spin_lock (&cq->lock); cq->pending--; // copy command out - *cmd = *cq->out; - cq->out = NEXTQ (cq->out, cq->start, cq->limit); + *cmd = *ptrs->out; + ptrs->out = NEXTQ (ptrs->out, ptrs->start, ptrs->limit); spin_unlock (&cq->lock); return 0; } else { + cq->filled++; spin_unlock (&cq->lock); return -EAGAIN; } @@ -796,7 +824,7 @@ static inline void fill_rx_pool (amb_dev * dev, unsigned char pool, int priority return; } if (check_area (skb->data, skb->truesize)) { - dev_kfree_skb (skb); + dev_kfree_skb_any (skb); return; } // cast needed as there is no %? for pointer differences @@ -805,14 +833,14 @@ static inline void fill_rx_pool (amb_dev * dev, unsigned char pool, int priority rx.handle = virt_to_bus (skb); rx.host_address = cpu_to_be32 (virt_to_bus (skb->data)); if (rx_give (dev, &rx, pool)) - dev_kfree_skb (skb); + dev_kfree_skb_any (skb); } return; } -// top up all RX pools (also called as a bottom half) +// top up all RX pools (can also be called as a bottom half) static void fill_rx_pools (amb_dev * dev) { unsigned char pool; @@ -827,25 +855,23 @@ static void fill_rx_pools (amb_dev * dev) { /********** enable host interrupts **********/ static inline void interrupts_on (amb_dev * dev) { - wr_mem (dev, &mem->interrupt_control, - rd_mem (dev, &mem->interrupt_control) - | AMB_INTERRUPT_BITS); + wr_plain (dev, &mem->interrupt_control, + rd_plain (dev, &mem->interrupt_control) + | AMB_INTERRUPT_BITS); } /********** disable host interrupts **********/ static inline void interrupts_off (amb_dev * dev) { - wr_mem (dev, &mem->interrupt_control, - rd_mem (dev, &mem->interrupt_control) - &~ AMB_INTERRUPT_BITS); + wr_plain (dev, &mem->interrupt_control, + rd_plain (dev, &mem->interrupt_control) + &~ AMB_INTERRUPT_BITS); } /********** interrupt handling **********/ static void interrupt_handler (int irq, void * dev_id, struct pt_regs * pt_regs) { amb_dev * dev = amb_devs; - unsigned int irq_ok; - unsigned int irq_ok_old; (void) pt_regs; PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler: %p", dev_id); @@ -860,50 +886,56 @@ static void interrupt_handler (int irq, void * dev_id, struct pt_regs * pt_regs) break; dev = dev->prev; } + // impossible - unless we add the device to our list after both + // registering the IRQ handler for it and enabling interrupts, AND + // the card generates an IRQ at startup - should not happen again if (!dev) { - PRINTD (DBG_IRQ, "irq not for me: %d", irq); + PRINTD (DBG_IRQ, "irq for unknown device: %d", irq); return; } + // impossible - unless we have memory corruption of dev or kernel if (irq != dev->irq) { PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq); return; } - // definitely for us - irq_ok = 0; - irq_ok_old = -1; + { + u32 interrupt = rd_plain (dev, &mem->interrupt); - // perhaps disable interrupts? (disabled at PIC by Linux) - // interrupts_off (dev); + // for us or someone else sharing the same interrupt + if (!interrupt) { + PRINTD (DBG_IRQ, "irq not for me: %d", irq); + return; + } + + // definitely for us + PRINTD (DBG_IRQ, "FYI: interrupt was %08x", interrupt); + wr_plain (dev, &mem->interrupt, -1); + } - while (irq_ok_old != irq_ok && irq_ok < 100) { + { + unsigned int irq_work = 0; unsigned char pool; - PRINTD (DBG_IRQ, "FYI: interrupt was %08x, work %u", - rd_mem (dev, &mem->interrupt), irq_ok); - wr_mem (dev, &mem->interrupt, -1); - irq_ok_old = irq_ok; for (pool = 0; pool < NUM_RX_POOLS; ++pool) while (!rx_take (dev, pool)) - ++irq_ok; + ++irq_work; while (!tx_take (dev)) - ++irq_ok; - } + ++irq_work; - if (irq_ok) { -#if 0 - queue_task (&dev->bh, &tq_immediate); - mark_bh (IMMEDIATE_BH); + if (irq_work) { +#ifdef FILL_RX_POOLS_IN_BH + queue_task (&dev->bh, &tq_immediate); + mark_bh (IMMEDIATE_BH); #else - fill_rx_pools (dev); + fill_rx_pools (dev); #endif - PRINTD (DBG_IRQ, "work done: %u", irq_ok); - } else { - PRINTD (DBG_IRQ|DBG_WARN, "no work done"); + PRINTD (DBG_IRQ, "work done: %u", irq_work); + } else { + PRINTD (DBG_IRQ|DBG_WARN, "no work done"); + } } - // perhaps re-enable interrupts? (re-enabled at PIC by Linux) - // interrupts_on (dev); PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler done: %p", dev_id); return; } @@ -913,6 +945,7 @@ static void interrupt_handler (int irq, void * dev_id, struct pt_regs * pt_regs) #ifdef DEBUG_AMBASSADOR static void dont_panic (amb_dev * dev) { amb_cq * cq = &dev->cq; + volatile amb_cq_ptrs * ptrs = &cq->ptrs; amb_txq * txq; amb_rxq * rxq; command * cmd; @@ -926,10 +959,11 @@ static void dont_panic (amb_dev * dev) { cli(); PRINTK (KERN_INFO, "don't panic - putting adapter into reset"); - wr_mem (dev, &mem->reset_control, rd_mem (dev, &mem->reset_control) | AMB_RESET); + wr_plain (dev, &mem->reset_control, + rd_plain (dev, &mem->reset_control) | AMB_RESET_BITS); PRINTK (KERN_INFO, "marking all commands complete"); - for (cmd = cq->start; cmd < cq->limit; ++cmd) + for (cmd = ptrs->start; cmd < ptrs->limit; ++cmd) cmd->request = cpu_to_be32 (SRB_COMPLETE); PRINTK (KERN_INFO, "completing all TXs"); @@ -952,7 +986,7 @@ static void dont_panic (amb_dev * dev) { if (rx == rxq->in.start) rx = rxq->in.limit; --rx; - dev_kfree_skb (bus_to_virt (rx->handle)); + dev_kfree_skb_any (bus_to_virt (rx->handle)); } } @@ -972,18 +1006,19 @@ static unsigned int make_rate (unsigned int rate, rounding r, PRINTD (DBG_FLOW|DBG_QOS, "make_rate %u", rate); - // rates in cells per second, ITU format (nasty 16bit fp) + // rates in cells per second, ITU format (nasty 16-bit floating-point) // given 5-bit e and 9-bit m: // rate = EITHER (1+m/2^9)*2^e OR 0 // bits = EITHER 1<<14 | e<<9 | m OR 0 // (bit 15 is "reserved", bit 14 "non-zero") // smallest rate is 0 (special representation) // largest rate is (1+511/512)*2^31 = 4290772992 (< 2^32-1) + // smallest non-zero rate is (1+0/512)*2^0 = 1 (> 0) // simple algorithm: // find position of top bit, this gives e // remove top bit and shift (rounding if feeling clever) by 9-e - // ucode bug: please don't set bit 14! 0 not representable + // ucode bug: please don't set bit 14! so 0 rate not representable if (rate > 0xffc00000U) { // larger than largest representable rate @@ -1228,7 +1263,7 @@ static int amb_open (struct atm_vcc * atm_vcc, short vpi, int vci) { // we are not really "immediately before allocating the connection // identifier in hardware", but it will just have to do! - atm_vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&atm_vcc->flags); if (txtp->traffic_class != ATM_NONE) { command cmd; @@ -1303,7 +1338,7 @@ static int amb_open (struct atm_vcc * atm_vcc, short vpi, int vci) { atm_vcc->vci = vci; // indicate readiness - atm_vcc->flags |= ATM_VF_READY; + set_bit(ATM_VF_READY,&atm_vcc->flags); MOD_INC_USE_COUNT; return 0; @@ -1319,7 +1354,7 @@ static void amb_close (struct atm_vcc * atm_vcc) { PRINTD (DBG_VCC|DBG_FLOW, "amb_close"); // indicate unreadiness - atm_vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&atm_vcc->flags); // disable TXing if (atm_vcc->qos.txtp.traffic_class != ATM_NONE) { @@ -1384,7 +1419,7 @@ static void amb_close (struct atm_vcc * atm_vcc) { kfree (vcc); // say the VPI/VCI is free again - atm_vcc->flags &= ~ATM_VF_ADDR; + clear_bit(ATM_VF_ADDR,&atm_vcc->flags); MOD_DEC_USE_COUNT; } @@ -1394,6 +1429,8 @@ static void amb_close (struct atm_vcc * atm_vcc) { static int amb_ioctl (struct atm_dev * dev, unsigned int cmd, void * arg) { unsigned short newdebug; if (cmd == AMB_SETDEBUG) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; if (copy_from_user (&newdebug, arg, sizeof(newdebug))) { // moan return -EFAULT; @@ -1402,6 +1439,8 @@ static int amb_ioctl (struct atm_dev * dev, unsigned int cmd, void * arg) { return 0; } } else if (cmd == AMB_DONTPANIC) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; dont_panic (dev); } else { // moan @@ -1453,7 +1492,7 @@ static int amb_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { } if (check_area (skb->data, skb->len)) { - atm_vcc->stats->tx_err++; + atomic_inc(&atm_vcc->stats->tx_err); return -ENOMEM; // ? } @@ -1564,7 +1603,7 @@ static void amb_free_rx_skb (struct atm_vcc * atm_vcc, struct sk_buff * skb) { // at. However, I note that the ATM layer calls kfree_skb rather // than dev_kfree_skb at this point so we are least covered as far // as buffer locking goes. There may be bugs if pcap clones RX skbs. - + PRINTD (DBG_FLOW|DBG_SKB, "amb_rx_free skb %p (atm_vcc %p, vcc %p)", skb, atm_vcc, vcc); @@ -1582,7 +1621,7 @@ static void amb_free_rx_skb (struct atm_vcc * atm_vcc, struct sk_buff * skb) { } // just do what the ATM layer would have done - kfree_skb (skb); + dev_kfree_skb_any (skb); return; } @@ -1733,12 +1772,12 @@ static int __init create_queues (amb_dev * dev, unsigned int cmds, cq->high = 0; cq->maximum = cmds - 1; - cq->start = cmd; - cq->in = cmd; - cq->out = cmd; - cq->limit = cmd + cmds; + cq->ptrs.start = cmd; + cq->ptrs.in = cmd; + cq->ptrs.out = cmd; + cq->ptrs.limit = cmd + cmds; - memory = cq->limit; + memory = cq->ptrs.limit; } PRINTD (DBG_TX, "TX queue pair at %p", memory); @@ -1810,7 +1849,7 @@ static int __init create_queues (amb_dev * dev, unsigned int cmds, static void destroy_queues (amb_dev * dev) { // all queues assumed empty - void * memory = dev->cq.start; + void * memory = dev->cq.ptrs.start; // includes txq.in, txq.out, rxq[].in and rxq[].out PRINTD (DBG_FLOW, "destroy_queues %p", dev); @@ -1823,9 +1862,8 @@ static void destroy_queues (amb_dev * dev) { /********** basic loader commands and error handling **********/ -static int __init do_loader_command (const amb_dev * dev, loader_command cmd, - volatile loader_block * lb) { - +static int __init do_loader_command (volatile loader_block * lb, + const amb_dev * dev, loader_command cmd) { // centisecond timeouts - guessing away here unsigned int command_timeouts [] = { [host_memory_test] = 15, @@ -1939,8 +1977,9 @@ static int __init do_loader_command (const amb_dev * dev, loader_command cmd, lb->result = 0; lb->command = cpu_to_be32 (cmd); lb->valid = cpu_to_be32 (DMA_VALID); + // dump_registers (dev); // dump_loader_block (lb); - wr_mem (dev, &mem->doorbell, virt_to_bus (lb)); + wr_mem (dev, &mem->doorbell, virt_to_bus (lb) & ~onegigmask); timeout = command_timeouts[cmd] * HZ/100; @@ -1957,7 +1996,7 @@ static int __init do_loader_command (const amb_dev * dev, loader_command cmd, if (cmd == adapter_start) { // wait for start command to acknowledge... timeout = HZ/10; - while (rd_mem (dev, &mem->doorbell)) + while (rd_plain (dev, &mem->doorbell)) if (timeout) { timeout = schedule_timeout (timeout); } else { @@ -1975,27 +2014,27 @@ static int __init do_loader_command (const amb_dev * dev, loader_command cmd, /* loader: determine loader version */ -static int __init get_loader_version (const amb_dev * dev, u32 * version) { - loader_block lb; +static int __init get_loader_version (loader_block * lb, + const amb_dev * dev, u32 * version) { int res; PRINTD (DBG_FLOW|DBG_LOAD, "get_loader_version"); - res = do_loader_command (dev, get_version_number, &lb); + res = do_loader_command (lb, dev, get_version_number); if (res) return res; if (version) - *version = be32_to_cpu (lb.payload.version); + *version = be32_to_cpu (lb->payload.version); return 0; } -/* loader: read or verify memory data blocks */ +/* loader: write memory data blocks */ -static int __init loader_write (const amb_dev * dev, const u32 * data, +static int __init loader_write (loader_block * lb, + const amb_dev * dev, const u32 * data, u32 address, unsigned int count) { unsigned int i; - loader_block lb; - transfer_block * tb = &lb.payload.transfer; + transfer_block * tb = &lb->payload.transfer; PRINTD (DBG_FLOW|DBG_LOAD, "loader_write"); @@ -2005,14 +2044,16 @@ static int __init loader_write (const amb_dev * dev, const u32 * data, tb->count = cpu_to_be32 (count); for (i = 0; i < count; ++i) tb->data[i] = cpu_to_be32 (data[i]); - return do_loader_command (dev, write_adapter_memory, &lb); + return do_loader_command (lb, dev, write_adapter_memory); } -static int __init loader_verify (const amb_dev * dev, const u32 * data, +/* loader: verify memory data blocks */ + +static int __init loader_verify (loader_block * lb, + const amb_dev * dev, const u32 * data, u32 address, unsigned int count) { unsigned int i; - loader_block lb; - transfer_block * tb = &lb.payload.transfer; + transfer_block * tb = &lb->payload.transfer; int res; PRINTD (DBG_FLOW|DBG_LOAD, "loader_verify"); @@ -2021,7 +2062,7 @@ static int __init loader_verify (const amb_dev * dev, const u32 * data, return -EINVAL; tb->address = cpu_to_be32 (address); tb->count = cpu_to_be32 (count); - res = do_loader_command (dev, read_adapter_memory, &lb); + res = do_loader_command (lb, dev, read_adapter_memory); if (!res) for (i = 0; i < count; ++i) if (tb->data[i] != cpu_to_be32 (data[i])) { @@ -2031,13 +2072,14 @@ static int __init loader_verify (const amb_dev * dev, const u32 * data, return res; } -static int __init loader_start (const amb_dev * dev, u32 address) { - loader_block lb; - +/* loader: start microcode */ + +static int __init loader_start (loader_block * lb, + const amb_dev * dev, u32 address) { PRINTD (DBG_FLOW|DBG_LOAD, "loader_start"); - lb.payload.start = cpu_to_be32 (address); - return do_loader_command (dev, adapter_start, &lb); + lb->payload.start = cpu_to_be32 (address); + return do_loader_command (lb, dev, adapter_start); } /********** reset card **********/ @@ -2047,19 +2089,21 @@ static int amb_reset (amb_dev * dev, int diags) { PRINTD (DBG_FLOW|DBG_LOAD, "amb_reset"); - word = rd_mem (dev, &mem->reset_control); -#if 0 - // clear all interrupts just in case - wr_mem (dev, &mem->interrupt, -1); -#endif + word = rd_plain (dev, &mem->reset_control); // put card into reset state - wr_mem (dev, &mem->reset_control, word | AMB_RESET); + wr_plain (dev, &mem->reset_control, word | AMB_RESET_BITS); // wait a short while udelay (10); +#if 1 + // put card into known good state + wr_plain (dev, &mem->interrupt_control, AMB_DOORBELL_BITS); + // clear all interrupts just in case + wr_plain (dev, &mem->interrupt, -1); +#endif // clear self-test done flag - wr_mem (dev, &mem->mb.loader.ready, 0); + wr_plain (dev, &mem->mb.loader.ready, 0); // take card out of reset state - wr_mem (dev, &mem->reset_control, word &~ AMB_RESET); + wr_plain (dev, &mem->reset_control, word &~ AMB_RESET_BITS); if (diags) { unsigned long timeout; @@ -2069,7 +2113,7 @@ static int amb_reset (amb_dev * dev, int diags) { timeout = schedule_timeout (timeout); // half second time-out timeout = HZ/2; - while (!rd_mem (dev, &mem->mb.loader.ready)) + while (!rd_plain (dev, &mem->mb.loader.ready)) if (timeout) { timeout = schedule_timeout (timeout); } else { @@ -2078,6 +2122,7 @@ static int amb_reset (amb_dev * dev, int diags) { } // get results of self-test + // XXX double check byte-order word = rd_mem (dev, &mem->mb.loader.result); if (word & SELF_TEST_FAILURE) { void sf (const char * msg) { @@ -2105,7 +2150,7 @@ static int amb_reset (amb_dev * dev, int diags) { /********** transfer and start the microcode **********/ -static int __init ucode_init (amb_dev * dev) { +static int __init ucode_init (loader_block * lb, amb_dev * dev) { unsigned int i = 0; unsigned int total = 0; const u32 * pointer = ucode_data; @@ -2125,10 +2170,10 @@ static int __init ucode_init (amb_dev * dev) { else words = MAX_TRANSFER_DATA; total += words; - res = loader_write (dev, pointer, address, words); + res = loader_write (lb, dev, pointer, address, words); if (res) return res; - res = loader_verify (dev, pointer, address, words); + res = loader_verify (lb, dev, pointer, address, words); if (res) return res; count -= words; @@ -2138,7 +2183,7 @@ static int __init ucode_init (amb_dev * dev) { i += 1; } if (*pointer == 0xdeadbeef) { - return loader_start (dev, ucode_start); + return loader_start (lb, dev, ucode_start); } else { // cast needed as there is no %? for pointer differnces PRINTD (DBG_LOAD|DBG_ERR, @@ -2156,14 +2201,14 @@ static int __init amb_talk (amb_dev * dev) { unsigned char pool; unsigned long timeout; - static inline u32 x (void * addr) { + u32 x (void * addr) { return cpu_to_be32 (virt_to_bus (addr)); } PRINTD (DBG_FLOW, "amb_talk %p", dev); - a.command_start = x (dev->cq.start); - a.command_end = x (dev->cq.limit); + a.command_start = x (dev->cq.ptrs.start); + a.command_end = x (dev->cq.ptrs.limit); a.tx_start = x (dev->txq.in.start); a.tx_end = x (dev->txq.in.limit); a.txcom_start = x (dev->txq.out.start); @@ -2192,7 +2237,7 @@ static int __init amb_talk (amb_dev * dev) { timeout = schedule_timeout (timeout); // give the adapter another half second? timeout = HZ/2; - while (rd_mem (dev, &mem->doorbell)) + while (rd_plain (dev, &mem->doorbell)) if (timeout) { timeout = schedule_timeout (timeout); } else { @@ -2259,38 +2304,55 @@ static void __init amb_esi (amb_dev * dev, u8 * esi) { } static int __init amb_init (amb_dev * dev) { - u32 version; + loader_block lb; + + void fixup_plx_window (void) { + // fix up the PLX-mapped window base address to match the block + unsigned long blb; + u32 mapreg; + blb = virt_to_bus (&lb); + // the kernel stack had better not ever cross a 1Gb boundary! + mapreg = rd_plain (dev, &mem->stuff[10]); + mapreg &= ~onegigmask; + mapreg |= blb & onegigmask; + wr_plain (dev, &mem->stuff[10], mapreg); + return; + } - /* enable adapter doorbell */ - wr_mem (dev, &mem->interrupt_control, - rd_mem (dev, &mem->interrupt_control) - | AMB_DOORBELL_BITS); + u32 version; if (amb_reset (dev, 1)) { PRINTK (KERN_ERR, "card reset failed!"); - } else if (get_loader_version (dev, &version)) { - PRINTK (KERN_INFO, "failed to get loader version"); } else { - PRINTK (KERN_INFO, "loader version is %08x", version); + fixup_plx_window (); - if (ucode_init (dev)) { - PRINTK (KERN_ERR, "microcode failure"); - } else if (create_queues (dev, cmds, txs, rxs, rxs_bs)) { - PRINTK (KERN_ERR, "failed to get memory for queues"); + if (get_loader_version (&lb, dev, &version)) { + PRINTK (KERN_INFO, "failed to get loader version"); } else { + PRINTK (KERN_INFO, "loader version is %08x", version); - if (amb_talk (dev)) { - PRINTK (KERN_ERR, "adapter did not accept queues"); + if (ucode_init (&lb, dev)) { + PRINTK (KERN_ERR, "microcode failure"); + } else if (create_queues (dev, cmds, txs, rxs, rxs_bs)) { + PRINTK (KERN_ERR, "failed to get memory for queues"); } else { - amb_ucode_version (dev); - return 0; - } /* amb_talk */ + if (amb_talk (dev)) { + PRINTK (KERN_ERR, "adapter did not accept queues"); + } else { + + amb_ucode_version (dev); + return 0; + + } /* amb_talk */ + + destroy_queues (dev); + } /* create_queues, ucode_init */ - destroy_queues (dev); - } /* create_queues, ucode_init */ + amb_reset (dev, 0); + } /* get_loader_version */ - } /* get_loader_version, amb_reset */ + } /* amb_reset */ return -1; } @@ -2303,81 +2365,57 @@ static int __init amb_probe (void) { amb_dev * dev; // read resources from PCI configuration space - u32 * membase = bus_to_virt - (pci_dev->resource[0].start); - u32 iobase = pci_dev->resource[1].start; u8 irq = pci_dev->irq; + u32 * membase = bus_to_virt (pci_dev->resource[0].start); + u32 iobase = pci_dev->resource[1].start; - // check IO region - if (check_region (iobase, AMB_EXTENT)) { - PRINTK (KERN_ERR, "IO range already in use!"); - return; - } - - dev = kmalloc (sizeof(amb_dev), GFP_KERNEL); - if (!dev) { - // perhaps we should be nice: deregister all adapters and abort? - PRINTK (KERN_ERR, "out of memory!"); - return; - } - memset (dev, 0, sizeof(amb_dev)); - - // set up known dev items straight away - dev->pci_dev = pci_dev; - - dev->iobase = iobase; - dev->irq = irq; - dev->membase = membase; - - // flags (currently only dead) - dev->flags = 0; - - // Allocate cell rates (fibre) - // ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53 - // to be really pedantic, this should be ATM_OC3c_PCR - dev->tx_avail = ATM_OC3_PCR; - dev->rx_avail = ATM_OC3_PCR; - -#if 0 - // initialise bottom half - dev->bh.next = 0; - dev->bh.sync = 0; - dev->bh.routine = (void (*)(void *)) fill_rx_pools; - dev->bh.data = dev; -#endif - - // semaphore for txer/rxer modifications - we cannot use a - // spinlock as the critical region needs to switch processes - init_MUTEX (&dev->vcc_sf); - // queue manipulation spinlocks; we want atomic reads and - // writes to the queue descriptors (handles IRQ and SMP) - // consider replacing "int pending" -> "atomic_t available" - // => problem related to who gets to move queue pointers - spin_lock_init (&dev->cq.lock); - spin_lock_init (&dev->txq.lock); - { + void setup_dev (void) { unsigned char pool; + memset (dev, 0, sizeof(amb_dev)); + + // set up known dev items straight away + dev->pci_dev = pci_dev; + + dev->iobase = iobase; + dev->irq = irq; + dev->membase = membase; + + // flags (currently only dead) + dev->flags = 0; + + // Allocate cell rates (fibre) + // ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53 + // to be really pedantic, this should be ATM_OC3c_PCR + dev->tx_avail = ATM_OC3_PCR; + dev->rx_avail = ATM_OC3_PCR; + +#ifdef FILL_RX_POOLS_IN_BH + // initialise bottom half + dev->bh.next = 0; + dev->bh.sync = 0; + dev->bh.routine = (void (*)(void *)) fill_rx_pools; + dev->bh.data = dev; +#endif + + // semaphore for txer/rxer modifications - we cannot use a + // spinlock as the critical region needs to switch processes + init_MUTEX (&dev->vcc_sf); + // queue manipulation spinlocks; we want atomic reads and + // writes to the queue descriptors (handles IRQ and SMP) + // consider replacing "int pending" -> "atomic_t available" + // => problem related to who gets to move queue pointers + spin_lock_init (&dev->cq.lock); + spin_lock_init (&dev->txq.lock); for (pool = 0; pool < NUM_RX_POOLS; ++pool) spin_lock_init (&dev->rxq[pool].lock); } - // grab (but share) IRQ and install handler - if (request_irq (irq, interrupt_handler, SA_SHIRQ, DEV_LABEL, dev)) { - PRINTK (KERN_ERR, "request IRQ failed!"); - // free_irq is at "endif" - } else { - + void setup_pci_dev (void) { unsigned char lat; - // reserve IO region - request_region (iobase, AMB_EXTENT, DEV_LABEL); - - PRINTD (DBG_INFO, "found Madge ATM adapter (amb) at IO %x, IRQ %u, MEM %p", - iobase, irq, membase); - // enable bus master accesses pci_set_master (pci_dev); - + // frobnicate latency (upwards, usually) pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &lat); if (pci_lat) { @@ -2389,43 +2427,78 @@ static int __init amb_probe (void) { "increasing", lat, MIN_PCI_LATENCY); pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY); } + } + + PRINTD (DBG_INFO, "found Madge ATM adapter (amb) at" + " IO %x, IRQ %u, MEM %p", iobase, irq, membase); + + // check IO region + if (check_region (iobase, AMB_EXTENT)) { + PRINTK (KERN_ERR, "IO range already in use!"); + return; + } + + dev = kmalloc (sizeof(amb_dev), GFP_KERNEL); + if (!dev) { + // perhaps we should be nice: deregister all adapters and abort? + PRINTK (KERN_ERR, "out of memory!"); + return; + } + + setup_dev(); + + if (amb_init (dev)) { + PRINTK (KERN_ERR, "adapter initialisation failure"); + } else { + + setup_pci_dev(); - if (amb_init (dev)) { - PRINTK (KERN_ERR, "adapter initialisation failure"); - } else if (!(dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, 0))) { - PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); + // grab (but share) IRQ and install handler + if (request_irq (irq, interrupt_handler, SA_SHIRQ, DEV_LABEL, dev)) { + PRINTK (KERN_ERR, "request IRQ failed!"); + // free_irq is at "endif" } else { - PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", - dev->atm_dev->number, dev, dev->atm_dev); - dev->atm_dev->dev_data = (void *) dev; + // reserve IO region + request_region (iobase, AMB_EXTENT, DEV_LABEL); - // register our address - amb_esi (dev, dev->atm_dev->esi); - - // 0 bits for vpi, 10 bits for vci - dev->atm_dev->ci_range.vpi_bits = NUM_VPI_BITS; - dev->atm_dev->ci_range.vci_bits = NUM_VCI_BITS; - - fill_rx_pools (dev); - - /* enable host interrupts */ - interrupts_on (dev); - - // update count and linked list - ++devs; - dev->prev = amb_devs; - amb_devs = dev; - // success - return; + dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL); + if (!dev->atm_dev) { + PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); + } else { + + PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", + dev->atm_dev->number, dev, dev->atm_dev); + dev->atm_dev->dev_data = (void *) dev; + + // register our address + amb_esi (dev, dev->atm_dev->esi); + + // 0 bits for vpi, 10 bits for vci + dev->atm_dev->ci_range.vpi_bits = NUM_VPI_BITS; + dev->atm_dev->ci_range.vci_bits = NUM_VCI_BITS; + + // update count and linked list + ++devs; + dev->prev = amb_devs; + amb_devs = dev; + + // enable host interrupts + interrupts_on (dev); + + // success + return; + + // not currently reached + atm_dev_deregister (dev->atm_dev); + } /* atm_dev_register */ - // not currently reached - atm_dev_deregister (dev->atm_dev); - } /* atm_dev_register, amb_init */ + release_region (iobase, AMB_EXTENT); + free_irq (irq, dev); + } /* request_region, request_irq */ - release_region (iobase, AMB_EXTENT); - free_irq (irq, dev); - } /* request_region, request_irq */ + amb_reset (dev, 0); + } /* amb_init */ kfree (dev); } /* kmalloc, end-of-fn */ @@ -2529,7 +2602,6 @@ int init_module (void) { show_version(); - // check arguments amb_check_args(); // get the juice @@ -2566,8 +2638,8 @@ void cleanup_module (void) { PRINTD (DBG_INFO|DBG_INIT, "closing %p (atm_dev = %p)", dev, dev->atm_dev); // the drain should not be necessary drain_rx_pools (dev); - amb_reset (dev, 0); interrupts_off (dev); + amb_reset (dev, 0); destroy_queues (dev); atm_dev_deregister (dev->atm_dev); free_irq (dev->irq, dev); @@ -2594,7 +2666,6 @@ int __init amb_detect (void) { show_version(); - // check arguments amb_check_args(); // get the juice diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h index 93e458644463..11ce866dab48 100644 --- a/drivers/atm/ambassador.h +++ b/drivers/atm/ambassador.h @@ -237,8 +237,6 @@ #define FP_155_RATE 0x24b1 #define FP_25_RATE 0x1f9d -#define AMB_RESET 0x40 - /* #define VERSION_NUMBER 0x01000000 // initial release */ /* #define VERSION_NUMBER 0x01010000 // fixed startup probs PLX MB0 not cleared */ /* #define VERSION_NUMBER 0x01020000 // changed SUNI reset timings; allowed r/w onchip */ @@ -333,9 +331,10 @@ typedef struct { u32 reset_control; } amb_mem; -/* IRQ (card to host) and doorbell (host to card) enable bits */ -#define AMB_INTERRUPT_BITS 0x00030000 -#define AMB_DOORBELL_BITS 0x00000300 +/* RESET bit, IRQ (card to host) and doorbell (host to card) enable bits */ +#define AMB_RESET_BITS 0x40000000 +#define AMB_INTERRUPT_BITS 0x00000300 +#define AMB_DOORBELL_BITS 0x00030000 /* loader commands */ @@ -543,14 +542,19 @@ typedef enum { ( (current)+1 < (limit) ? (current)+1 : (start) ) typedef struct { - spinlock_t lock; - unsigned int pending; - unsigned int high; - unsigned int maximum; // size - 1 (q implementation) command * start; command * in; command * out; command * limit; +} amb_cq_ptrs; + +typedef struct { + spinlock_t lock; + unsigned int pending; + unsigned int high; + unsigned int filled; + unsigned int maximum; // size - 1 (q implementation) + amb_cq_ptrs ptrs; } amb_cq; typedef struct { diff --git a/drivers/atm/atmdev_init.c b/drivers/atm/atmdev_init.c index 357cbdbe0120..443831a82b8a 100644 --- a/drivers/atm/atmdev_init.c +++ b/drivers/atm/atmdev_init.c @@ -39,7 +39,7 @@ int __init atmdev_init(void) devs = 0; #ifdef CONFIG_ATM_ENI - devs += eni_detect(); +// devs += eni_detect(); #endif #ifdef CONFIG_ATM_ZATM devs += zatm_detect(); diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index cc13eb06f50f..64c25420eb3b 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */ @@ -36,12 +38,14 @@ struct atmtcp_dev_data { static int atmtcp_send_control(struct atm_vcc *vcc,int type, - const struct atmtcp_control *msg,unsigned short flag) + const struct atmtcp_control *msg,int flag) { + DECLARE_WAITQUEUE(wait,current); struct atm_vcc *out_vcc; struct sk_buff *skb; struct atmtcp_control *new_msg; - unsigned short old_flags; + int old_test; + int error = 0; out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; if (!out_vcc) return -EUNATCH; @@ -60,16 +64,21 @@ static int atmtcp_send_control(struct atm_vcc *vcc,int type, new_msg->type = type; memset(&new_msg->vcc,0,sizeof(atm_kptr_t)); *(struct atm_vcc **) &new_msg->vcc = vcc; - old_flags = vcc->flags; + old_test = test_bit(flag,&vcc->flags); out_vcc->push(out_vcc,skb); - while (!((vcc->flags ^ old_flags) & flag)) { + add_wait_queue(&vcc->sleep,&wait); + while (test_bit(flag,&vcc->flags) == old_test) { mb(); out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; - if (!out_vcc) return -EUNATCH; - sleep_on(&vcc->sleep); - + if (!out_vcc) { + error = -EUNATCH; + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); } - return 0; + remove_wait_queue(&vcc->sleep,&wait); + return error; } @@ -83,10 +92,10 @@ static int atmtcp_recv_control(const struct atmtcp_control *msg) vcc->reply = msg->result; switch (msg->type) { case ATMTCP_CTRL_OPEN: - vcc->flags ^= ATM_VF_READY; + change_bit(ATM_VF_READY,&vcc->flags); break; case ATMTCP_CTRL_CLOSE: - vcc->flags ^= ATM_VF_ADDR; + change_bit(ATM_VF_ADDR,&vcc->flags); break; default: printk(KERN_ERR "atmtcp_recv_control: unknown type %d\n", @@ -120,8 +129,8 @@ static int atmtcp_v_open(struct atm_vcc *vcc,short vpi,int vci) if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0; msg.type = ATMTCP_CTRL_OPEN; msg.qos = vcc->qos; - vcc->flags |= ATM_VF_ADDR; - vcc->flags &= ~ATM_VF_READY; /* just in case ... */ + set_bit(ATM_VF_ADDR,&vcc->flags); + clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */ error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY); if (error) return error; return vcc->reply; @@ -136,7 +145,7 @@ static void atmtcp_v_close(struct atm_vcc *vcc) msg.addr.sap_family = AF_ATMPVC; msg.addr.sap_addr.vpi = vcc->vpi; msg.addr.sap_addr.vci = vcc->vci; - vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); (void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR); } @@ -168,13 +177,18 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) struct atmtcp_hdr *hdr; int size; + if (vcc->qos.txtp.traffic_class == ATM_NONE) { + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); + return -EINVAL; + } dev_data = PRIV(vcc->dev); if (dev_data) out_vcc = dev_data->vcc; if (!dev_data || !out_vcc) { if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); if (dev_data) return 0; - vcc->stats->tx_err++; + atomic_inc(&vcc->stats->tx_err); return -ENOLINK; } size = skb->len+sizeof(struct atmtcp_hdr); @@ -182,7 +196,7 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) if (!new_skb) { if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); - vcc->stats->tx_err++; + atomic_inc(&vcc->stats->tx_err); return -ENOBUFS; } hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr)); @@ -193,8 +207,8 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); out_vcc->push(out_vcc,new_skb); - vcc->stats->tx++; - out_vcc->stats->rx++; + atomic_inc(&vcc->stats->tx); + atomic_inc(&out_vcc->stats->rx); return 0; } @@ -251,7 +265,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) out_vcc->qos.rxtp.traffic_class != ATM_NONE) break; if (!out_vcc) { - vcc->stats->tx_err++; + atomic_inc(&vcc->stats->tx_err); goto done; } skb_pull(skb,sizeof(struct atmtcp_hdr)); @@ -263,8 +277,8 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) new_skb->stamp = xtime; memcpy(skb_put(new_skb,skb->len),skb->data,skb->len); out_vcc->push(out_vcc,new_skb); - vcc->stats->tx++; - out_vcc->stats->rx++; + atomic_inc(&vcc->stats->tx); + atomic_inc(&out_vcc->stats->rx); done: if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); @@ -305,7 +319,7 @@ static struct atm_dev atmtcp_control_dev = { 999, /* dummy device number */ NULL,NULL, /* pretend not to have any VCCs */ NULL,NULL, /* no data */ - 0, /* no flags */ + { 0 }, /* no flags */ NULL, /* no local address */ { 0 } /* no ESI, no statistics */ }; @@ -318,7 +332,7 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result) dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL); if (!dev_data) return -ENOMEM; - dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,0); + dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL); if (!dev) { kfree(dev_data); return itf == -1 ? -ENOMEM : -EBUSY; @@ -352,7 +366,8 @@ int atmtcp_attach(struct atm_vcc *vcc,int itf) } PRIV(dev)->vcc = vcc; bind_vcc(vcc,&atmtcp_control_dev); - vcc->flags |= ATM_VF_READY | ATM_VF_META; + set_bit(ATM_VF_META,&vcc->flags); + set_bit(ATM_VF_READY,&vcc->flags); vcc->dev_data = dev; (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */ vcc->stats = &atmtcp_control_dev.stats.aal5; diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 081fcdfed28d..b3240d498957 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -526,7 +528,7 @@ static int rx_aal0(struct atm_vcc *vcc) DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n", vcc->dev->number); length = 0; - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); } else { length = ATM_CELL_SIZE-1; /* no HEC */ @@ -581,7 +583,7 @@ static int rx_aal5(struct atm_vcc *vcc) size); } eff = length = 0; - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); } else { size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2); @@ -598,7 +600,7 @@ static int rx_aal5(struct atm_vcc *vcc) "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n", vcc->dev->number,vcc->vci,length,size << 2,descr); length = eff = 0; - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); } } skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL; @@ -663,6 +665,7 @@ static void poll_rx(struct atm_dev *dev) if (rx_vcc(curr)) return; eni_dev->fast = ENI_VCC(curr)->next; ENI_VCC(curr)->next = ENI_VCC_NOS; + barrier(); ENI_VCC(curr)->servicing--; } while ((curr = eni_dev->slow)) { @@ -670,6 +673,7 @@ static void poll_rx(struct atm_dev *dev) if (rx_vcc(curr)) return; eni_dev->slow = ENI_VCC(curr)->next; ENI_VCC(curr)->next = ENI_VCC_NOS; + barrier(); ENI_VCC(curr)->servicing--; } } @@ -768,7 +772,7 @@ rx_dequeued++; vcc->push(vcc,skb); pushed++; } - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } wake_up(&eni_dev->rx_wait); } @@ -836,10 +840,10 @@ static int open_rx_second(struct atm_vcc *vcc) static void close_rx(struct atm_vcc *vcc) { - unsigned long here,flags; + DECLARE_WAITQUEUE(wait,current); + unsigned long here; struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; - u32 tmp; eni_vcc = ENI_VCC(vcc); if (!eni_vcc->rx) return; @@ -858,25 +862,41 @@ static void close_rx(struct atm_vcc *vcc) /* wait for RX queue to drain */ DPRINTK("eni_close: waiting for RX ...\n"); EVENT("RX closing\n",0,0); - save_flags(flags); - cli(); - while (eni_vcc->rxing || eni_vcc->servicing) { + add_wait_queue(&eni_dev->rx_wait,&wait); + set_current_state(TASK_UNINTERRUPTIBLE); + barrier(); + for (;;) { + /* transition service->rx: rxing++, servicing-- */ + if (!eni_vcc->servicing) { + barrier(); + if (!eni_vcc->rxing) break; + } EVENT("drain PDUs (rx %ld, serv %ld)\n",eni_vcc->rxing, eni_vcc->servicing); printk(KERN_INFO "%d+%d RX left\n",eni_vcc->servicing, eni_vcc->rxing); - sleep_on(&eni_dev->rx_wait); + schedule(); + set_current_state(TASK_UNINTERRUPTIBLE); } - while (eni_vcc->rx_pos != (tmp = - readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ)>> - MID_VCI_READ_SHIFT) { + for (;;) { + unsigned long flags; + int at_end; + u32 tmp; + + spin_lock_irqsave(&eni_dev->lock,flags); + tmp = readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ; + at_end = eni_vcc->rx_pos == tmp >> MID_VCI_READ_SHIFT; + spin_unlock_irqrestore(&eni_dev->lock,flags); + if (at_end) break; EVENT("drain discard (host 0x%lx, nic 0x%lx)\n", eni_vcc->rx_pos,tmp); printk(KERN_INFO "draining RX: host 0x%lx, nic 0x%x\n", eni_vcc->rx_pos,tmp); - sleep_on(&eni_dev->rx_wait); + schedule(); + set_current_state(TASK_UNINTERRUPTIBLE); } - restore_flags(flags); + set_current_state(TASK_RUNNING); + remove_wait_queue(&eni_dev->rx_wait,&wait); } eni_free_mem(eni_dev,eni_vcc->recv,eni_vcc->words << 2); eni_vcc->rx = NULL; @@ -1054,8 +1074,9 @@ static enum enq_res do_tx(struct sk_buff *skb) * 1 DMA xfer & 2 DMA'ed bytes (protocol layering is for wimps :-) */ + aal5 = vcc->qos.aal == ATM_AAL5; /* check space in buffer */ - if (!(aal5 = vcc->qos.aal == ATM_AAL5)) + if (!aal5) size = (ATM_CELL_PAYLOAD >> 2)+TX_DESCR_SIZE; /* cell without HEC plus segmentation header (includes four-byte cell header) */ @@ -1207,7 +1228,7 @@ static void dequeue_tx(struct atm_dev *dev) PCI_DMA_TODEVICE); if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb_irq(skb); - vcc->stats->tx++; + atomic_inc(&vcc->stats->tx); wake_up(&eni_dev->tx_wait); dma_complete++; } @@ -1366,34 +1387,40 @@ static int open_tx_second(struct atm_vcc *vcc) static void close_tx(struct atm_vcc *vcc) { + DECLARE_WAITQUEUE(wait,current); struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; - unsigned long flags; eni_vcc = ENI_VCC(vcc); if (!eni_vcc->tx) return; eni_dev = ENI_DEV(vcc->dev); /* wait for TX queue to drain */ DPRINTK("eni_close: waiting for TX ...\n"); - save_flags(flags); - cli(); - while (skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing) { + add_wait_queue(&eni_dev->tx_wait,&wait); + set_current_state(TASK_UNINTERRUPTIBLE); + for (;;) { + unsigned long flags; + int txing; + + spin_lock_irqsave(&eni_dev->lock,flags); + txing = skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing; + spin_unlock_irqrestore(&eni_dev->lock,flags); + if (!txing) break; DPRINTK("%d TX left\n",eni_vcc->txing); - sleep_on(&eni_dev->tx_wait); - } - /* - * Looping a few times in here is probably far cheaper than keeping - * track of TX completions all the time, so let's poll a bit ... - */ - while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) != - eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index))) schedule(); - restore_flags(flags); -#if 0 - if (skb_peek(&eni_vcc->tx->backlog)) - printk(KERN_CRIT DEV_LABEL "SKBs in BACKLOG !!!\n"); -#endif + set_current_state(TASK_UNINTERRUPTIBLE); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&eni_dev->tx_wait,&wait); if (eni_vcc->tx != eni_dev->ubr) { + /* + * Looping a few times in here is probably far cheaper than + * keeping track of TX completions all the time, so let's poll + * a bit ... + */ + while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) != + eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index))) + schedule(); eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2); eni_vcc->tx->send = 0; eni_dev->tx_bw += eni_vcc->tx->reserved; @@ -1496,28 +1523,36 @@ static void eni_int(int irq,void *dev_id,struct pt_regs *regs) if (reason & MID_RX_DMA_COMPLETE) { EVENT("INT: RX DMA complete, starting dequeue_rx\n", 0,0); + spin_lock(&eni_dev->lock); dequeue_rx(dev); EVENT("dequeue_rx done, starting poll_rx\n",0,0); poll_rx(dev); + spin_unlock(&eni_dev->lock); EVENT("poll_rx done\n",0,0); /* poll_tx ? */ } if (reason & MID_SERVICE) { EVENT("INT: service, starting get_service\n",0,0); + spin_lock(&eni_dev->lock); get_service(dev); EVENT("get_service done, starting poll_rx\n",0,0); poll_rx(dev); + spin_unlock(&eni_dev->lock); EVENT("poll_rx done\n",0,0); } if (reason & MID_TX_DMA_COMPLETE) { EVENT("INT: TX DMA COMPLETE\n",0,0); + spin_lock(&eni_dev->lock); dequeue_tx(dev); + spin_unlock(&eni_dev->lock); } if (reason & MID_TX_COMPLETE) { EVENT("INT: TX COMPLETE\n",0,0); tx_complete++; - wake_up(&eni_dev->tx_wait); + spin_lock(&eni_dev->lock); poll_tx(dev); + spin_unlock(&eni_dev->lock); + wake_up(&eni_dev->tx_wait); /* poll_rx ? */ } if (reason & (MID_STAT_OVFL | MID_SUNI_INT | MID_DMA_ERR_ACK | @@ -1532,7 +1567,7 @@ tx_complete++; /*--------------------------------- entries ---------------------------------*/ -static const char *media_name[] __initdata = { +static const char *media_name[] __devinitdata = { "MMF", "SMF", "MMF", "03?", /* 0- 3 */ "UTP", "05?", "06?", "07?", /* 4- 7 */ "TAXI","09?", "10?", "11?", /* 8-11 */ @@ -1556,7 +1591,7 @@ static const char *media_name[] __initdata = { } }) -static int __init get_esi_asic(struct atm_dev *dev) +static int __devinit get_esi_asic(struct atm_dev *dev) { struct eni_dev *eni_dev; unsigned char tonga; @@ -1648,7 +1683,7 @@ static int __init get_esi_asic(struct atm_dev *dev) #undef GET_SEPROM -static int __init get_esi_fpga(struct atm_dev *dev,unsigned long base) +static int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base) { unsigned long mac_base; int i; @@ -1659,7 +1694,7 @@ static int __init get_esi_fpga(struct atm_dev *dev,unsigned long base) } -static int __init eni_init(struct atm_dev *dev) +static int __devinit eni_do_init(struct atm_dev *dev) { struct midway_eprom *eprom; struct eni_dev *eni_dev; @@ -1748,7 +1783,7 @@ static int __init eni_init(struct atm_dev *dev) } -static int __init eni_start(struct atm_dev *dev) +static int __devinit eni_start(struct atm_dev *dev) { struct eni_dev *eni_dev; unsigned long buf,buffer_mem; @@ -1788,6 +1823,7 @@ static int __init eni_start(struct atm_dev *dev) DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n", eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma, eni_dev->service,buf); + spin_lock_init(&eni_dev->lock); /* initialize memory management */ buffer_mem = eni_dev->mem-(buf-eni_dev->ram); eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2; @@ -1830,14 +1866,14 @@ static void eni_close(struct atm_vcc *vcc) { DPRINTK(">eni_close\n"); if (!ENI_VCC(vcc)) return; - vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); close_rx(vcc); close_tx(vcc); DPRINTK("eni_close: done waiting\n"); /* deallocate memory */ kfree(ENI_VCC(vcc)); ENI_VCC(vcc) = NULL; - vcc->flags &= ~ATM_VF_ADDR; + clear_bit(ATM_VF_ADDR,&vcc->flags); /*foo();*/ } @@ -1855,8 +1891,8 @@ static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci) if (vcc->qos.txtp.traffic_class != ATM_NONE) { for (walk = vcc->dev->vccs; walk; walk = walk->next) - if ((walk->flags & ATM_VF_ADDR) && - walk->vci == *vci && + if (test_bit(ATM_VF_ADDR,&walk->flags) + && walk->vci == *vci && walk->qos.txtp.traffic_class != ATM_NONE) break; @@ -1872,7 +1908,7 @@ static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci) return -EADDRINUSE; if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; for (walk = vcc->dev->vccs; walk; walk = walk->next) - if ((walk->flags & ATM_VF_ADDR) && walk->vci == *vci && + if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci && walk->qos.txtp.traffic_class != ATM_NONE) return -EADDRINUSE; return 0; @@ -1887,19 +1923,19 @@ static int eni_open(struct atm_vcc *vcc,short vpi,int vci) DPRINTK(">eni_open\n"); EVENT("eni_open\n",0,0); - if (!(vcc->flags & ATM_VF_PARTIAL)) ENI_VCC(vcc) = NULL; + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ENI_VCC(vcc) = NULL; eni_dev = ENI_DEV(vcc->dev); error = get_ci(vcc,&vpi,&vci); if (error) return error; vcc->vpi = vpi; vcc->vci = vci; if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) - vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&vcc->flags); if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5) return -EINVAL; DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi, vcc->vci); - if (!(vcc->flags & ATM_VF_PARTIAL)) { + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { eni_vcc = kmalloc(sizeof(struct eni_vcc),GFP_KERNEL); if (!eni_vcc) return -ENOMEM; ENI_VCC(vcc) = eni_vcc; @@ -1922,7 +1958,7 @@ static int eni_open(struct atm_vcc *vcc,short vpi,int vci) eni_close(vcc); return error; } - vcc->flags |= ATM_VF_READY; + set_bit(ATM_VF_READY,&vcc->flags); /* should power down SUNI while !ref_count @@@ */ return 0; } @@ -1953,8 +1989,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs) * Walk through the send buffer and patch the rate information in all * segmentation buffer descriptors of this VCC. */ - save_flags(flags); - cli(); + spin_lock_irqsave(&eni_dev->lock,flags); for (skb = eni_dev->tx_queue.next; skb != (struct sk_buff *) &eni_dev->tx_queue; skb = skb->next) { unsigned long dsc; @@ -1965,7 +2000,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs) (tx->prescaler << MID_SEG_PR_SHIFT) | (tx->resolution << MID_SEG_RATE_SHIFT), dsc); } - restore_flags(flags); + spin_unlock_irqrestore(&eni_dev->lock,flags); return 0; } @@ -2049,14 +2084,13 @@ static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb) } submitted++; ATM_SKB(skb)->vcc = vcc; - save_flags(flags); - cli(); /* brute force */ + spin_lock_irqsave(&ENI_DEV(vcc->dev)->lock,flags); /* brute force */ if (skb_peek(&ENI_VCC(vcc)->tx->backlog) || do_tx(skb)) { skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb); ENI_VCC(vcc)->tx->backlog_len++; backlogged++; } - restore_flags(flags); + spin_unlock_irqrestore(&ENI_DEV(vcc->dev)->lock,flags); return 0; } @@ -2206,79 +2240,86 @@ static const struct atmdev_ops ops = { }; -int __init eni_detect(void) +static int __devinit eni_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *ent) { struct atm_dev *dev; struct eni_dev *eni_dev; - int devs,type; - struct sk_buff *skb; + int error = -ENOMEM; - DPRINTK("eni_detect\n"); - if (sizeof(skb->cb) < sizeof(struct eni_skb_prv)) { - printk(KERN_ERR "eni_detect: skb->cb is too small (%d < %d)\n", - sizeof(skb->cb),sizeof(struct eni_skb_prv)); - return 0; - } - eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev), - GFP_KERNEL); + DPRINTK("eni_init_one\n"); + eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL); if (!eni_dev) return -ENOMEM; - devs = 0; - for (type = 0; type < 2; type++) { - struct pci_dev *pci_dev; - - pci_dev = NULL; - while ((pci_dev = pci_find_device(PCI_VENDOR_ID_EF,type ? - PCI_DEVICE_ID_EF_ATM_ASIC : PCI_DEVICE_ID_EF_ATM_FPGA, - pci_dev))) { - if (!devs) { - cpu_zeroes = pci_alloc_consistent(pci_dev, - ENI_ZEROES_SIZE,&zeroes); - if (!cpu_zeroes) { - kfree(eni_dev); - return -ENOMEM; - } - } - dev = atm_dev_register(DEV_LABEL,&ops,-1,0); - if (!dev) break; - eni_dev->pci_dev = pci_dev; - ENI_DEV(dev) = eni_dev; - eni_dev->asic = type; - if (eni_init(dev) || eni_start(dev)) { - atm_dev_deregister(dev); - break; - } - eni_dev->more = eni_boards; - eni_boards = dev; - devs++; - eni_dev = (struct eni_dev *) kmalloc(sizeof(struct - eni_dev),GFP_KERNEL); - if (!eni_dev) break; - } - } - if (!devs && cpu_zeroes) { - pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE, - cpu_zeroes,zeroes); - cpu_zeroes = NULL; - } + if (!cpu_zeroes) { + cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE, + &zeroes); + if (!cpu_zeroes) goto out1; + } + dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL); + if (!dev) goto out2; + pci_dev->driver_data = dev; + eni_dev->pci_dev = pci_dev; + ENI_DEV(dev) = eni_dev; + eni_dev->asic = ent->driver_data; + error = eni_do_init(dev); + if (error) goto out3; + error = eni_start(dev); + if (error) goto out3; + eni_dev->more = eni_boards; + eni_boards = dev; + MOD_INC_USE_COUNT; /* @@@ we don't support unloading yet */ + return 0; +out3: + atm_dev_deregister(dev); +out2: + pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes); + cpu_zeroes = NULL; +out1: kfree(eni_dev); - return devs; + return error; } -#ifdef MODULE +static struct pci_device_id eni_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_FPGA, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 /* FPGA */ }, + { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 1 /* ASIC */ }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci,eni_pci_tbl); + -int init_module(void) +static void __devexit eni_remove_one(struct pci_dev *pci_dev) { - if (!eni_detect()) { - printk(KERN_ERR DEV_LABEL ": no adapter found\n"); - return -ENXIO; + /* grrr */ +} + + +static struct pci_driver eni_driver = { + name: DEV_LABEL, + id_table: eni_pci_tbl, + probe: eni_init_one, + remove: eni_remove_one, +}; + + +static int __init eni_init(void) +{ + struct sk_buff *skb; /* dummy for sizeof */ + + if (sizeof(skb->cb) < sizeof(struct eni_skb_prv)) { + printk(KERN_ERR "eni_detect: skb->cb is too small (%d < %d)\n", + sizeof(skb->cb),sizeof(struct eni_skb_prv)); + return -EIO; } - MOD_INC_USE_COUNT; - return 0; + if (pci_register_driver(&eni_driver) > 0) return 0; + pci_unregister_driver (&eni_driver); + return -ENODEV; } -void cleanup_module(void) +static void __exit eni_cleanup(void) { /* * Well, there's no way to get rid of the driver yet, so we don't @@ -2286,4 +2327,6 @@ void cleanup_module(void) */ } -#endif + +module_init(eni_init); +module_exit(eni_cleanup); diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index 76d0dd482fe2..23ba60fb1e9e 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "midway.h" @@ -65,6 +66,8 @@ struct eni_vcc { }; struct eni_dev { + /*-------------------------------- spinlock */ + spinlock_t lock; /* sync with interrupt */ /*-------------------------------- base pointers into Midway address space */ unsigned long phy; /* PHY interface chip registers */ diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 4c07f2e7f164..96c022842703 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -1,5 +1,5 @@ /* - $Id: fore200e.c,v 1.1 2000/02/21 16:04:31 davem Exp $ + $Id: fore200e.c,v 1.2 2000/03/21 21:19:24 davem Exp $ A FORE Systems 200E-series driver for ATM on Linux. Christophe Lizzi (lizzi@cnam.fr), October 1999-February 2000. @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_ATM_FORE200E_PCA #include @@ -67,7 +69,7 @@ #define FORE200E_52BYTE_AAL0_SDU #endif -#define FORE200E_VERSION "0.2a" +#define FORE200E_VERSION "0.2b" #define FORE200E "fore200e: " @@ -187,10 +189,10 @@ fore200e_kfree(void* chunk) /* allocate and align a chunk of memory intended to hold the data behing exchanged - between the driver and the adapter (using streaming DVMA on SBUS hosts) */ + between the driver and the adapter (using streaming DVMA) */ static int -fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment) +fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment, int direction) { unsigned long offset = 0; @@ -199,6 +201,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i chunk->alloc_size = size + alignment; chunk->align_size = size; + chunk->direction = direction; chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA); if (chunk->alloc_addr == NULL) @@ -209,7 +212,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i chunk->align_addr = chunk->alloc_addr + offset; - chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size); + chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size, direction); return 0; } @@ -220,7 +223,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i static void fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk) { - fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size); + fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction); fore200e_kfree(chunk->alloc_addr); } @@ -463,34 +466,32 @@ static void fore200e_pca_write(u32 val, volatile u32* addr) static u32 -fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size) +fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) { - u32 dma_addr = pci_map_single((struct pci_dev*)fore200e->bus_dev, virt_addr, size, PCI_DMA_BIDIRECTIONAL); + u32 dma_addr = pci_map_single((struct pci_dev*)fore200e->bus_dev, virt_addr, size, direction); - DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d --> dma_addr = 0x%08x\n", - virt_addr, size, dma_addr); + DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d, --> dma_addr = 0x%08x\n", + virt_addr, size, direction, dma_addr); return dma_addr; } static void -fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size) +fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) { - DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d\n", dma_addr, size); + DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, - PCI_DMA_BIDIRECTIONAL); + pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction); } static void -fore200e_pca_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size) +fore200e_pca_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int direction) { - DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d\n", dma_addr, size); + DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - pci_dma_sync_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, - PCI_DMA_BIDIRECTIONAL); + pci_dma_sync_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction); } @@ -511,10 +512,8 @@ fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int chunk->align_addr = chunk->alloc_addr; #else - if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment) < 0) + if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment, FORE200E_DMA_BIDIRECTIONAL) < 0) return -ENOMEM; - - chunk->dma_addr = fore200e_pca_dma_map(fore200e, chunk->align_addr, chunk->align_size); #endif return 0; @@ -532,8 +531,6 @@ fore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) chunk->alloc_addr, chunk->dma_addr); #else - fore200e_pca_dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size); - fore200e_chunk_free(fore200e, chunk); #endif } @@ -685,7 +682,7 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) opcode.opcode = OPCODE_GET_PROM; opcode.pad = 0; - prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data)); + prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE); fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr); @@ -697,7 +694,7 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) *entry->status = STATUS_FREE; - fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data)); + fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE); if (ok == 0) { printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name); @@ -748,31 +745,32 @@ fore200e_sba_write(u32 val, volatile u32* addr) static u32 -fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size) +fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) { - u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size); + u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction); - DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d --> dma_addr = 0x%08x\n", virt_addr, size, dma_addr); + DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", + virt_addr, size, direction, dma_addr); return dma_addr; } static void -fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size) +fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) { - DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d\n", dma_addr, size); + DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction); - sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size); + sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); } static void -fore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size) +fore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int direction) { - DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d\n", dma_addr, size); + DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - sbus_dma_sync_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size); + sbus_dma_sync_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); } @@ -1002,7 +1000,8 @@ fore200e_irq_tx(struct fore200e* fore200e) kfree(entry->data); /* remove DMA mapping */ - fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length); + fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length, + FORE200E_DMA_TODEVICE); /* notify tx completion */ if (entry->vcc->pop) @@ -1012,9 +1011,9 @@ fore200e_irq_tx(struct fore200e* fore200e) /* check error condition */ if (*entry->status & STATUS_ERROR) - entry->vcc->stats->tx_err++; + atomic_inc(&entry->vcc->stats->tx_err); else - entry->vcc->stats->tx++; + atomic_inc(&entry->vcc->stats->tx); *entry->status = STATUS_FREE; @@ -1127,7 +1126,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct rpd* rpd) if (skb == NULL) { printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len); - vcc->stats->rx_drop++; + atomic_inc(&vcc->stats->rx_drop); return; } @@ -1146,7 +1145,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct rpd* rpd) buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle); /* ensure DMA synchronisation */ - fore200e->bus->dma_sync(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length); + fore200e->bus->dma_sync(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, FORE200E_DMA_FROMDEVICE); memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length); } @@ -1169,7 +1168,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct rpd* rpd) } vcc->push(vcc, skb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } @@ -1404,7 +1403,7 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci) if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0; - vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&vcc->flags); vcc->itf = vcc->dev->number; DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; " @@ -1467,7 +1466,7 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci) fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = 65536; fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0; - vcc->flags |= ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); return 0; } @@ -1552,11 +1551,14 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) if(--retry > 0) goto retry_here; - vcc->stats->tx_err++; + atomic_inc(&vcc->stats->tx_err); printk(FORE200E "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n", fore200e->name, fore200e->cp_queues->heartbeat); - + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb(skb); return -EIO; } } @@ -1584,6 +1586,10 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) if (entry->data == NULL) { spin_unlock_irqrestore(&fore200e->tx_lock, flags); + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb(skb); return -ENOMEM; } @@ -1591,11 +1597,11 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) if (skb_len < tx_len) memset(entry->data + skb_len, 0x00, tx_len - skb_len); - tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len); + tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len, FORE200E_DMA_TODEVICE); } else { entry->data = NULL; - tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len); + tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len, FORE200E_DMA_TODEVICE); } tpd->tsd[ 0 ].length = tx_len; @@ -1606,7 +1612,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) spin_unlock_irqrestore(&fore200e->tx_lock, flags); /* ensure DMA synchronisation */ - fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length); + fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE); DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal), @@ -1661,27 +1667,29 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) { int ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 10); - fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length); + fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length, + FORE200E_DMA_TODEVICE); - if (ok == 0) { - printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci); - - entry->vcc->stats->tx_err++; - return -EIO; - } - entry->vcc->stats->tx++; - - DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci); - /* free tmp copy of misaligned data */ if (entry->data) kfree(entry->data); - + /* notify tx completion */ if (vcc->pop) vcc->pop(vcc, skb); else dev_kfree_skb(skb); + + if (ok == 0) { + printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci); + + atomic_inc(&entry->vcc->stats->tx_err); + return -EIO; + } + atomic_inc(&entry->vcc->stats->tx); + + DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci); + } #endif @@ -1704,7 +1712,7 @@ fore200e_getstats(struct fore200e* fore200e) return -ENOMEM; } - stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats)); + stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats), FORE200E_DMA_FROMDEVICE); FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); @@ -1721,7 +1729,7 @@ fore200e_getstats(struct fore200e* fore200e) *entry->status = STATUS_FREE; - fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats)); + fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), FORE200E_DMA_FROMDEVICE); if (ok == 0) { printk(FORE200E "unable to get statistics from device %s\n", fore200e->name); @@ -1766,7 +1774,7 @@ fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs) int ok; u32 oc3_regs_dma_addr; - oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs)); + oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE); FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); @@ -1785,7 +1793,7 @@ fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs) *entry->status = STATUS_FREE; - fore200e->bus_dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs)); + fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE); if (ok == 0) { printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name); @@ -1842,16 +1850,16 @@ fore200e_setloop(struct fore200e* fore200e, int loop_mode) switch (loop_mode) { - case SUNI_LM_NONE: + case ATM_LM_NONE: mct_value = 0; mct_mask = SUNI_MCT_DLE | SUNI_MCT_LLE; break; - case SUNI_LM_DIAG: + case ATM_LM_LOC_PHY: mct_value = mct_mask = SUNI_MCT_DLE; break; - case SUNI_LM_LOOP: + case ATM_LM_RMT_PHY: mct_value = mct_mask = SUNI_MCT_LLE; break; @@ -1921,12 +1929,16 @@ fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void* arg) case SONET_GETDIAG: return put_user(0, (int*)arg) ? -EFAULT : 0; - - case SUNI_SETLOOP: + + case ATM_SETLOOP: return fore200e_setloop(fore200e, (int)(unsigned long)arg); - case SUNI_GETLOOP: + case ATM_GETLOOP: return put_user(fore200e->loop_mode, (int*)arg) ? -EFAULT : 0; + + case ATM_QUERYLOOP: + return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ? + -EFAULT : 0; } return -ENOSYS; /* not implemented */ @@ -1967,7 +1979,7 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags) /* update rate control parameters */ fore200e_rate_ctrl(qos, &fore200e_vcc->rate); - vcc->flags |= ATM_VF_HASQOS; + set_bit(ATM_VF_HASQOS,&vcc->flags); return 0; } @@ -2051,7 +2063,8 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e) /* allocate the receive buffer body */ if (fore200e_chunk_alloc(fore200e, - &buffer[ i ].data, size, fore200e->bus->buffer_alignment) < 0) { + &buffer[ i ].data, size, fore200e->bus->buffer_alignment, + FORE200E_DMA_FROMDEVICE) < 0) { while (i > 0) fore200e_chunk_free(fore200e, &buffer[ --i ].data); @@ -2485,7 +2498,8 @@ fore200e_register(struct fore200e* fore200e) DPRINTK(2, "device %s being registered\n", fore200e->name); - atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1, 0); + atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1, + NULL); if (atm_dev == NULL) { printk(FORE200E "unable to register device %s\n", fore200e->name); return -ENODEV; @@ -2690,17 +2704,29 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) static const char* oc3_mode[] = { "normal operation", "diagnostic loopback", - "line loopback" + "line loopback", + "unknown" }; u32 fw_release = fore200e->bus->read(&fore200e->cp_queues->fw_release); u32 mon960_release = fore200e->bus->read(&fore200e->cp_queues->mon960_release); u32 oc3_revision = fore200e->bus->read(&fore200e->cp_queues->oc3_revision); u32 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type)); + u32 oc3_index; if (media_index < 0 || media_index > 4) media_index = 5; + switch(fore200e->loop_mode) { + case ATM_LM_NONE: oc3_index = 0; + break; + case ATM_LM_LOC_PHY: oc3_index = 1; + break; + case ATM_LM_RMT_PHY: oc3_index = 2; + break; + default: oc3_index = 3; + } + return sprintf(page, " firmware release:\t\t%d.%d.%d\n" " monitor release:\t\t%d.%d\n" @@ -2711,7 +2737,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) mon960_release >> 16, mon960_release << 16 >> 16, media_name[ media_index ], oc3_revision, - oc3_mode[ fore200e->loop_mode ]); + oc3_mode[ oc3_index ]); } if (!left--) { diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index eea20162bca6..fb7d92259631 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -559,6 +559,7 @@ typedef struct chunk { void* alloc_addr; /* base address of allocated chunk */ void* align_addr; /* base address of aligned chunk */ u32 dma_addr; /* DMA address of aligned chunk */ + int direction; /* direction of DMA mapping */ u32 alloc_size; /* length of allocated chunk */ u32 align_size; /* length of aligned chunk */ } chunk_t; @@ -796,9 +797,9 @@ typedef struct fore200e_bus { const unsigned int* fw_size; /* address of firmware data size */ u32 (*read)(volatile u32*); void (*write)(u32, volatile u32*); - u32 (*dma_map)(struct fore200e*, void*, int); - void (*dma_unmap)(struct fore200e*, u32, int); - void (*dma_sync)(struct fore200e*, u32, int); + u32 (*dma_map)(struct fore200e*, void*, int, int); + void (*dma_unmap)(struct fore200e*, u32, int, int); + void (*dma_sync)(struct fore200e*, u32, int, int); int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); void (*dma_chunk_free)(struct fore200e*, struct chunk*); struct fore200e* (*detect)(const struct fore200e_bus*, int); @@ -814,6 +815,31 @@ typedef struct fore200e_bus { } fore200e_bus_t; +#if defined(CONFIG_ATM_FORE200E_SBA) +# if defined(CONFIG_ATM_FORE200E_PCA) +# if (PCI_DMA_BIDIRECTIONAL == SBUS_DMA_BIDIRECTIONAL) && \ + (PCI_DMA_TODEVICE == SBUS_DMA_TODEVICE) && \ + (PCI_DMA_FROMDEVICE == SBUS_DMA_FROMDEVICE) +# define FORE200E_DMA_BIDIRECTIONAL PCI_DMA_BIDIRECTIONAL +# define FORE200E_DMA_TODEVICE PCI_DMA_TODEVICE +# define FORE200E_DMA_FROMDEVICE PCI_DMA_FROMDEVICE +# else + /* in that case, we'll need to add an extra indirection, e.g. + fore200e->bus->dma_direction[ fore200e_dma_direction ] */ +# error PCI and SBUS DMA direction flags differ! +# endif +# else +# define FORE200E_DMA_BIDIRECTIONAL SBA_DMA_BIDIRECTIONAL +# define FORE200E_DMA_TODEVICE SBA_DMA_TODEVICE +# define FORE200E_DMA_FROMDEVICE SBA_DMA_FROMDEVICE +# endif +#else +# define FORE200E_DMA_BIDIRECTIONAL PCI_DMA_BIDIRECTIONAL +# define FORE200E_DMA_TODEVICE PCI_DMA_TODEVICE +# define FORE200E_DMA_FROMDEVICE PCI_DMA_FROMDEVICE +#endif + + /* per-device data */ typedef struct fore200e { diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 0a412667e2a7..f0dff701117b 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -50,7 +51,7 @@ #define maintainer_string "Giuliano Procida at Madge Networks " #define description_string "Madge ATM Horizon [Ultra] driver" -#define version_string "1.2" +#define version_string "1.2.1" static inline void __init show_version (void) { printk ("%s version %s\n", description_string, version_string); @@ -246,7 +247,7 @@ static inline void __init show_version (void) { Atomic test and set tx_busy until we succeed; we should implement some sort of timeout so that tx_busy will never be stuck at true. - If no TX channel is setup for this VC we wait for an idle one (if + If no TX channel is set up for this VC we wait for an idle one (if necessary) and set it up. At this point we have a TX channel ready for use. We wait for enough @@ -276,7 +277,7 @@ static inline void __init show_version (void) { available handler is locked out over the same period. Data available on the card triggers an interrupt. If the data is not - suitable for out existing RX channels or we cannot allocate a buffer + suitable for our existing RX channels or we cannot allocate a buffer it is flushed. Otherwise an RX receive is scheduled. Multiple RX transfers may be scheduled for the same frame. @@ -321,7 +322,7 @@ static inline void __init show_version (void) { and the frame continues to be received. The solution is to make sure any received frames are flushed when - ready. This is currently done just before the solution to 3. + ready. This is currently done just before the solution to 2. 4. PCI bus (original Horizon only, fixed in Ultra) @@ -608,7 +609,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, u32 pre; // local fn to build the timer bits - inline int set_cr (void) { + int set_cr (void) { // paranoia if (div > CR_MAXD || (!pre) || pre > 1<vcc->pop) { ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb); } else { - dev_kfree_skb (skb); + dev_kfree_skb_any (skb); } } @@ -961,12 +962,11 @@ static void hrz_close_rx (hrz_dev * dev, u16 vc) { static void rx_schedule (hrz_dev * dev, int irq) { unsigned int rx_bytes; - int pio_instead; + int pio_instead = 0; #ifndef TAILRECURSIONWORKS - do { + pio_instead = 1; + while (pio_instead) { #endif - pio_instead = 0; - // bytes waiting for RX transfer rx_bytes = dev->rx_bytes; @@ -1047,7 +1047,7 @@ static void rx_schedule (hrz_dev * dev, int irq) { { struct atm_vcc * vcc = ATM_SKB(skb)->vcc; // VC layer stats - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); skb->stamp = xtime; // end of our responsability vcc->push (vcc, skb); @@ -1078,12 +1078,12 @@ static void rx_schedule (hrz_dev * dev, int irq) { #ifdef TAILRECURSIONWORKS // and we all bless optimised tail calls if (pio_instead) - rx_schedule (dev, 0); + return rx_schedule (dev, 0); return; #else // grrrrrrr! irq = 0; - } while (pio_instead); + } return; #endif } @@ -1130,11 +1130,11 @@ static void tx_schedule (hrz_dev * const dev, int irq) { int append_desc = 0; - int pio_instead; + int pio_instead = 0; #ifndef TAILRECURSIONWORKS - do { + pio_instead = 1; + while (pio_instead) { #endif - pio_instead = 0; // bytes in current region waiting for TX transfer tx_bytes = dev->tx_bytes; @@ -1201,7 +1201,7 @@ static void tx_schedule (hrz_dev * const dev, int irq) { dev->tx_iovec = 0; // VC layer stats - ATM_SKB(skb)->vcc->stats->tx++; + atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); // free the skb hrz_kfree_skb (skb); @@ -1236,12 +1236,12 @@ static void tx_schedule (hrz_dev * const dev, int irq) { #ifdef TAILRECURSIONWORKS // and we all bless optimised tail calls if (pio_instead) - tx_schedule (dev, 0); + return tx_schedule (dev, 0); return; #else // grrrrrrr! irq = 0; - } while (pio_instead); + } return; #endif } @@ -1340,37 +1340,33 @@ static inline void rx_data_av_handler (hrz_dev * dev) { if (atm_vcc->qos.rxtp.traffic_class != ATM_NONE) { if (rx_len <= atm_vcc->qos.rxtp.max_sdu) { - struct sk_buff *skb = atm_alloc_charge(atm_vcc,rx_len,GFP_ATOMIC); - - // If everyone has to call atm_pdu2... why isn't it part of - // atm_charge? B'cos some people already have skb->truesize! - // WA: well. even if they think they do, they might not ... :-) - - if (skb) { - // remember this so we can push it later - dev->rx_skb = skb; - // remember this so we can flush it later - dev->rx_channel = rx_channel; - - // prepare socket buffer - skb_put (skb, rx_len); - ATM_SKB(skb)->vcc = atm_vcc; - - // simple transfer - // dev->rx_regions = 0; - // dev->rx_iovec = 0; - dev->rx_bytes = rx_len; - dev->rx_addr = skb->data; - PRINTD (DBG_RX, "RX start simple transfer (addr %p, len %d)", - skb->data, rx_len); - - // do the business - rx_schedule (dev, 0); - return; - - } else { - PRINTD (DBG_INFO, "failed to get skb"); - } + + struct sk_buff * skb = atm_alloc_charge (atm_vcc, rx_len, GFP_ATOMIC); + if (skb) { + // remember this so we can push it later + dev->rx_skb = skb; + // remember this so we can flush it later + dev->rx_channel = rx_channel; + + // prepare socket buffer + skb_put (skb, rx_len); + ATM_SKB(skb)->vcc = atm_vcc; + + // simple transfer + // dev->rx_regions = 0; + // dev->rx_iovec = 0; + dev->rx_bytes = rx_len; + dev->rx_addr = skb->data; + PRINTD (DBG_RX, "RX start simple transfer (addr %p, len %d)", + skb->data, rx_len); + + // do the business + rx_schedule (dev, 0); + return; + + } else { + PRINTD (DBG_SKB|DBG_WARN, "failed to get skb"); + } } else { PRINTK (KERN_INFO, "frame received on TX-only VC %x", rx_channel); @@ -1662,6 +1658,7 @@ static int hrz_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { if (!channel) { PRINTD (DBG_ERR|DBG_TX, "attempt to transmit on zero (rx_)channel"); + hrz_kfree_skb (skb); return -EIO; } @@ -1699,9 +1696,11 @@ static int hrz_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { #endif // wait until TX is free and grab lock - if (tx_hold (dev)) + if (tx_hold (dev)) { + hrz_kfree_skb (skb); return -ERESTARTSYS; - + } + // Wait for enough space to be available in transmit buffer memory. // should be number of cells needed + 2 (according to hardware docs) @@ -1722,6 +1721,7 @@ static int hrz_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { PRINTD (DBG_TX|DBG_ERR, "spun out waiting for tx buffers, got %d of %d", free_buffers, buffers_required); tx_release (dev); + hrz_kfree_skb (skb); return -ERESTARTSYS; } } @@ -1820,12 +1820,12 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) { u32 ctrl = rd_regl (dev, CONTROL_0_REG); - inline void WRITE_IT_WAIT (void) { + void WRITE_IT_WAIT (void) { wr_regl (dev, CONTROL_0_REG, ctrl); udelay (5); } - inline void CLOCK_IT (void) { + void CLOCK_IT (void) { // DI must be valid around rising SK edge ctrl &= ~SEEPROM_SK; WRITE_IT_WAIT(); @@ -2530,7 +2530,7 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) { // this is "immediately before allocating the connection identifier // in hardware" - so long as the next call does not fail :) - atm_vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&atm_vcc->flags); // any errors here are very serious and should never occur @@ -2554,7 +2554,7 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) { atm_vcc->dev_data = (void *) vccp; // indicate readiness - atm_vcc->flags |= ATM_VF_READY; + set_bit(ATM_VF_READY,&atm_vcc->flags); MOD_INC_USE_COUNT; return 0; @@ -2569,7 +2569,7 @@ static void hrz_close (struct atm_vcc * atm_vcc) { PRINTD (DBG_VCC|DBG_FLOW, "hrz_close"); // indicate unreadiness - atm_vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&atm_vcc->flags); if (atm_vcc->qos.txtp.traffic_class != ATM_NONE) { unsigned int i; @@ -2611,7 +2611,7 @@ static void hrz_close (struct atm_vcc * atm_vcc) { // free our structure kfree (vcc); // say the VPI/VCI is free again - atm_vcc->flags &= ~ATM_VF_ADDR; + clear_bit(ATM_VF_ADDR,&atm_vcc->flags); MOD_DEC_USE_COUNT; } @@ -2758,13 +2758,13 @@ static int __init hrz_probe (void) { devs = 0; pci_dev = NULL; while ((pci_dev = pci_find_device - (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, pci_dev) - )) { + (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, pci_dev) + )) { hrz_dev * dev; // adapter slot free, read resources from PCI configuration space u32 iobase = pci_dev->resource[0].start; - u32 * membase = bus_to_virt(pci_dev->resource[1].start); + u32 * membase = bus_to_virt (pci_dev->resource[1].start); u8 irq = pci_dev->irq; // check IO region @@ -2795,7 +2795,7 @@ static int __init hrz_probe (void) { PRINTD (DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p", iobase, irq, membase); - dev->atm_dev = atm_dev_register (DEV_LABEL, &hrz_ops, -1, 0); + dev->atm_dev = atm_dev_register (DEV_LABEL, &hrz_ops, -1, NULL); if (!(dev->atm_dev)) { PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); } else { diff --git a/drivers/atm/horizon.h b/drivers/atm/horizon.h index be5e5c726c28..6655bdc1cf96 100644 --- a/drivers/atm/horizon.h +++ b/drivers/atm/horizon.h @@ -31,10 +31,8 @@ #define DRIVER_ATM_HORIZON_H #include - #include - #ifdef CONFIG_ATM_HORIZON_DEBUG #define DEBUG_HORIZON #endif diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index 3d305858aa22..31503ed1e6b7 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -157,36 +157,54 @@ static int fetch_stats(struct atm_dev *dev,struct idt77105_stats *arg,int zero) } +static int set_loopback(struct atm_dev *dev,int mode) +{ + int diag; + + diag = GET(DIAG) & ~IDT77105_DIAG_LCMASK; + switch (mode) { + case ATM_LM_NONE: + break; + case ATM_LM_LOC_ATM: + diag |= IDT77105_DIAG_LC_PHY_LOOPBACK; + break; + case ATM_LM_RMT_ATM: + diag |= IDT77105_DIAG_LC_LINE_LOOPBACK; + break; + default: + return -EINVAL; + } + PUT(diag,DIAG); + printk(KERN_NOTICE "%s(%d) Loopback mode is: %s\n", dev->type, + dev->number, + (mode == ATM_LM_NONE ? "NONE" : + (mode == ATM_LM_LOC_ATM ? "DIAG (local)" : + (mode == IDT77105_DIAG_LC_LINE_LOOPBACK ? "LOOP (remote)" : + "unknown"))) + ); + PRIV(dev)->loop_mode = mode; + return 0; +} + static int idt77105_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) { printk(KERN_NOTICE "%s(%d) idt77105_ioctl() called\n",dev->type,dev->number); switch (cmd) { case IDT77105_GETSTATZ: + if (!capable(CAP_NET_ADMIN)) return -EPERM; + /* fall through */ case IDT77105_GETSTAT: return fetch_stats(dev,(struct idt77105_stats *) arg, cmd == IDT77105_GETSTATZ); - case IDT77105_SETLOOP: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if ((int) arg < 0 || (int) arg > IDT77105_LM_LOOP) - return -EINVAL; - PUT((GET(DIAG) & ~IDT77105_DIAG_LCMASK) | - ((int) arg == IDT77105_LM_NONE ? IDT77105_DIAG_LC_NORMAL : 0) | - ((int) arg == IDT77105_LM_DIAG ? IDT77105_DIAG_LC_PHY_LOOPBACK : 0) | - ((int) arg == IDT77105_LM_LOOP ? IDT77105_DIAG_LC_LINE_LOOPBACK : 0), - DIAG); - printk(KERN_NOTICE "%s(%d) Loopback mode is: %s\n", - dev->type, dev->number, - ((int) arg == IDT77105_LM_NONE ? "NONE" : - ((int) arg == IDT77105_LM_DIAG ? "DIAG (local)" : - ((int) arg == IDT77105_LM_LOOP ? "LOOP (remote)" : - "unknown"))) - ); - PRIV(dev)->loop_mode = (int) arg; - return 0; - case IDT77105_GETLOOP: + case ATM_SETLOOP: + return set_loopback(dev,(int) (long) arg); + case ATM_GETLOOP: return put_user(PRIV(dev)->loop_mode,(int *) arg) ? - -EFAULT : sizeof(int); + -EFAULT : 0; + case ATM_QUERYLOOP: + return put_user(ATM_LM_LOC_ATM | ATM_LM_RMT_ATM, + (int *) arg) ? -EFAULT : 0; default: return -ENOIOCTLCMD; } @@ -266,13 +284,13 @@ static int idt77105_start(struct atm_dev *dev) /* initialise loop mode from hardware */ switch ( GET(DIAG) & IDT77105_DIAG_LCMASK ) { case IDT77105_DIAG_LC_NORMAL: - PRIV(dev)->loop_mode = IDT77105_LM_NONE; + PRIV(dev)->loop_mode = ATM_LM_NONE; break; case IDT77105_DIAG_LC_PHY_LOOPBACK: - PRIV(dev)->loop_mode = IDT77105_LM_DIAG; + PRIV(dev)->loop_mode = ATM_LM_LOC_ATM; break; case IDT77105_DIAG_LC_LINE_LOOPBACK: - PRIV(dev)->loop_mode = IDT77105_LM_LOOP; + PRIV(dev)->loop_mode = ATM_LM_RMT_ATM; break; } diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 84bdda6d660e..cd1714a53b09 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,7 @@ #include "suni.h" #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8)) struct suni_priv { - struct sonet_stats sonet_stats; /* link diagnostics */ + struct k_sonet_stats sonet_stats; /* link diagnostics */ unsigned char loop_mode; /* loopback mode */ struct atm_dev *dev; /* device back-pointer */ struct suni_priv *next; /* next SUNI */ @@ -625,12 +626,12 @@ static int ia_que_tx (IADEV *iadev) { num_desc = ia_avail_descs(iadev); while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { if (!(vcc = ATM_SKB(skb)->vcc)) { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); printk("ia_que_tx: Null vcc\n"); break; } - if ((vcc->flags & ATM_VF_READY) == 0 ) { - dev_kfree_skb(skb); + if (!test_bit(ATM_VF_READY,&vcc->flags)) { + dev_kfree_skb_any(skb); printk("Free the SKB on closed vci %d \n", vcc->vci); break; } @@ -658,14 +659,14 @@ void ia_tx_poll (IADEV *iadev) { vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("ia_tx_poll: vcc is null\n"); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } iavcc = INPH_IA_VCC(vcc); if (!iavcc) { printk("ia_tx_poll: iavcc is null\n"); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } @@ -682,7 +683,7 @@ void ia_tx_poll (IADEV *iadev) { (long)skb1);) } else - dev_kfree_skb(skb1); + dev_kfree_skb_any(skb1); skb1 = skb_dequeue(&iavcc->txing_skb); } if (!skb1) { @@ -696,7 +697,7 @@ void ia_tx_poll (IADEV *iadev) { IF_EVENT(printk("Tx Done - skb 0x%lx return\n",(long)skb);) } else - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); kfree(rtne); } ia_que_tx(iadev); @@ -1128,7 +1129,7 @@ static int rx_pkt(struct atm_dev *dev) status = (u_short) (buf_desc_ptr->desc_mode); if (status & (RX_CER | RX_PTE | RX_OFL)) { - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); IF_ERR(printk("IA: bad packet, dropping it");) if (status & RX_CER) { IF_ERR(printk(" cause: packet CRC error\n");) @@ -1152,7 +1153,7 @@ static int rx_pkt(struct atm_dev *dev) len = dma_addr - buf_addr; if (len > iadev->rx_buf_sz) { printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz); - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); free_desc(dev, desc); return 0; } @@ -1166,7 +1167,7 @@ static int rx_pkt(struct atm_dev *dev) if (!skb) { IF_ERR(printk("can't allocate memory for recv, drop pkt!\n");) - vcc->stats->rx_drop++; + atomic_inc(&vcc->stats->rx_drop); atm_return(vcc, atm_pdu2truesize(len)); free_desc(dev, desc); return 0; @@ -1297,7 +1298,7 @@ static void rx_dle_intr(struct atm_dev *dev) if (!skb->len) { printk("rx_dle_intr: skb len 0\n"); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } else { @@ -1308,15 +1309,15 @@ static void rx_dle_intr(struct atm_dev *dev) vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("IA: null vcc\n"); - vcc->stats->rx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->rx_err); + dev_kfree_skb_any(skb); goto INCR_DLE; } ia_vcc = INPH_IA_VCC(vcc); if (ia_vcc == NULL) { - vcc->stats->rx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->rx_err); + dev_kfree_skb_any(skb); #if LINUX_VERSION_CODE >= 0x20312 atm_return(vcc, atm_guess_pdu2truesize(skb->len)); #else @@ -1331,8 +1332,8 @@ static void rx_dle_intr(struct atm_dev *dev) if ((length > iadev->rx_buf_sz) || (length > (skb->len - sizeof(struct cpcs_trailer)))) { - vcc->stats->rx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->rx_err); + dev_kfree_skb_any(skb); IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)", length, skb->len);) #if LINUX_VERSION_CODE >= 0x20312 @@ -1351,7 +1352,7 @@ static void rx_dle_intr(struct atm_dev *dev) IF_RX(printk("rx_dle_intr: skb push");) vcc->push(vcc,skb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); iadev->rx_pkt_cnt++; } INCR_DLE: @@ -1710,13 +1711,13 @@ static void tx_dle_intr(struct atm_dev *dev) vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("tx_dle_intr: vcc is null\n"); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } iavcc = INPH_IA_VCC(vcc); if (!iavcc) { printk("tx_dle_intr: iavcc is null\n"); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } if (vcc->qos.txtp.pcr >= iadev->rate_limit) { @@ -1725,7 +1726,7 @@ static void tx_dle_intr(struct atm_dev *dev) vcc->pop(vcc, skb); } else { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } } else { /* Hold the rate-limited skb for flow control */ @@ -2601,7 +2602,7 @@ static void ia_close(struct atm_vcc *vcc) IF_EVENT(printk("ia_close: ia_vcc->vc_desc_cnt = %d vci = %d\n", ia_vcc->vc_desc_cnt,vcc->vci);) - vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); skb_queue_head_init (&tmp_tx_backlog); skb_queue_head_init (&tmp_vcc_backlog); if (vcc->qos.txtp.traffic_class != ATM_NONE) { @@ -2611,7 +2612,7 @@ static void ia_close(struct atm_vcc *vcc) while((skb = skb_dequeue(&iadev->tx_backlog))) { if (ATM_SKB(skb)->vcc == vcc){ if (vcc->pop) vcc->pop(vcc, skb); - else dev_kfree_skb(skb); + else dev_kfree_skb_any(skb); } else skb_queue_tail(&tmp_tx_backlog, skb); @@ -2669,7 +2670,7 @@ static void ia_close(struct atm_vcc *vcc) kfree(INPH_IA_VCC(vcc)); ia_vcc = NULL; INPH_IA_VCC(vcc) = NULL; - vcc->flags &= ~ATM_VF_ADDR; + clear_bit(ATM_VF_ADDR,&vcc->flags); return; } @@ -2678,7 +2679,7 @@ static int ia_open(struct atm_vcc *vcc, short vpi, int vci) IADEV *iadev; struct ia_vcc *ia_vcc; int error; - if (!(vcc->flags & ATM_VF_PARTIAL)) + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { IF_EVENT(printk("ia: not partially allocated resources\n");) INPH_IA_VCC(vcc) = NULL; @@ -2695,7 +2696,7 @@ static int ia_open(struct atm_vcc *vcc, short vpi, int vci) if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) { IF_EVENT(printk("iphase open: unspec part\n");) - vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&vcc->flags); } if (vcc->qos.aal != ATM_AAL5) return -EINVAL; @@ -2721,7 +2722,7 @@ static int ia_open(struct atm_vcc *vcc, short vpi, int vci) return error; } - vcc->flags |= ATM_VF_READY; + set_bit(ATM_VF_READY,&vcc->flags); #ifndef MODULE { @@ -2749,7 +2750,7 @@ static int ia_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags) static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) { - PIA_CMDBUF ia_cmds; + IA_CMDBUF ia_cmds; IADEV *iadev; int i, board; u16 *tmps; @@ -2757,34 +2758,37 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) if (cmd != IA_CMD) { if (!dev->phy->ioctl) return -EINVAL; return dev->phy->ioctl(dev,cmd,arg); - } - ia_cmds = (PIA_CMDBUF)arg; - board = ia_cmds->status; + } + if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT; + board = ia_cmds.status; if ((board < 0) || (board > iadev_count)) board = 0; iadev = ia_dev[board]; - switch (ia_cmds->cmd) { + switch (ia_cmds.cmd) { case MEMDUMP: { - switch (ia_cmds->sub_cmd) { + switch (ia_cmds.sub_cmd) { case MEMDUMP_DEV: - memcpy((char*)ia_cmds->buf, (char*)iadev, - sizeof(IADEV)); - ia_cmds->status = 0; + if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (copy_to_user(ia_cmds.buf, iadev, sizeof(IADEV))) + return -EFAULT; + ia_cmds.status = 0; break; case MEMDUMP_SEGREG: - tmps = (u16 *)ia_cmds->buf; + if (!capable(CAP_NET_ADMIN)) return -EPERM; + tmps = (u16 *)ia_cmds.buf; for(i=0; i<0x80; i+=2, tmps++) - *tmps = *(u16*)(iadev->seg_reg+i); - ia_cmds->status = 0; - ia_cmds->len = 0x80; + if(put_user(*(u16*)(iadev->seg_reg+i), tmps)) return -EFAULT; + ia_cmds.status = 0; + ia_cmds.len = 0x80; break; case MEMDUMP_REASSREG: - tmps = (u16 *)ia_cmds->buf; + if (!capable(CAP_NET_ADMIN)) return -EPERM; + tmps = (u16 *)ia_cmds.buf; for(i=0; i<0x80; i+=2, tmps++) - *tmps = *(u16*)(iadev->reass_reg+i); - ia_cmds->status = 0; - ia_cmds->len = 0x80; + if(put_user(*(u16*)(iadev->reass_reg+i), tmps)) return -EFAULT; + ia_cmds.status = 0; + ia_cmds.len = 0x80; break; case MEMDUMP_FFL: { @@ -2792,6 +2796,7 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) ffredn_t *ffL = ®s_local.ffredn; rfredn_t *rfL = ®s_local.rfredn; + if (!capable(CAP_NET_ADMIN)) return -EPERM; /* Copy real rfred registers into the local copy */ for (i=0; i<(sizeof (rfredn_t))/4; i++) ((u_int *)rfL)[i] = ((u_int *)iadev->reass_reg)[i] & 0xffff; @@ -2799,63 +2804,67 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) for (i=0; i<(sizeof (ffredn_t))/4; i++) ((u_int *)ffL)[i] = ((u_int *)iadev->seg_reg)[i] & 0xffff; - memcpy((char*)ia_cmds->buf,(char*)®s_local,sizeof(ia_regs_t)); + if (copy_to_user(ia_cmds.buf, ®s_local,sizeof(ia_regs_t))) + return -EFAULT; printk("Board %d registers dumped\n", board); - ia_cmds->status = 0; + ia_cmds.status = 0; } break; case READ_REG: { + if (!capable(CAP_NET_ADMIN)) return -EPERM; desc_dbg(iadev); - ia_cmds->status = 0; + ia_cmds.status = 0; } break; case 0x6: { - ia_cmds->status = 0; + ia_cmds.status = 0; printk("skb = 0x%lx\n", (long)skb_peek(&iadev->tx_backlog)); printk("rtn_q: 0x%lx\n",(long)ia_deque_rtn_q(&iadev->tx_return_q)); } break; case 0x8: { - struct sonet_stats *stats; + struct k_sonet_stats *stats; stats = &PRIV(_ia_dev[board])->sonet_stats; - printk("section_bip: %d\n", stats->section_bip); - printk("line_bip : %d\n", stats->line_bip); - printk("path_bip : %d\n", stats->path_bip); - printk("line_febe : %d\n", stats->line_febe); - printk("path_febe : %d\n", stats->path_febe); - printk("corr_hcs : %d\n", stats->corr_hcs); - printk("uncorr_hcs : %d\n", stats->uncorr_hcs); - printk("tx_cells : %d\n", stats->tx_cells); - printk("rx_cells : %d\n", stats->rx_cells); + printk("section_bip: %d\n", atomic_read(&stats->section_bip)); + printk("line_bip : %d\n", atomic_read(&stats->line_bip)); + printk("path_bip : %d\n", atomic_read(&stats->path_bip)); + printk("line_febe : %d\n", atomic_read(&stats->line_febe)); + printk("path_febe : %d\n", atomic_read(&stats->path_febe)); + printk("corr_hcs : %d\n", atomic_read(&stats->corr_hcs)); + printk("uncorr_hcs : %d\n", atomic_read(&stats->uncorr_hcs)); + printk("tx_cells : %d\n", atomic_read(&stats->tx_cells)); + printk("rx_cells : %d\n", atomic_read(&stats->rx_cells)); } - ia_cmds->status = 0; + ia_cmds.status = 0; break; case 0x9: + if (!capable(CAP_NET_ADMIN)) return -EPERM; for (i = 1; i <= iadev->num_rx_desc; i++) free_desc(_ia_dev[board], i); writew( ~(RX_FREEQ_EMPT | RX_EXCP_RCVD), iadev->reass_reg+REASS_MASK_REG); iadev->rxing = 1; - ia_cmds->status = 0; + ia_cmds.status = 0; break; case 0xb: + if (!capable(CAP_NET_ADMIN)) return -EPERM; IaFrontEndIntr(iadev); break; case 0xa: + if (!capable(CAP_NET_ADMIN)) return -EPERM; { - ia_cmds->status = 0; - IADebugFlag = ia_cmds->maddr; + ia_cmds.status = 0; + IADebugFlag = ia_cmds.maddr; printk("New debug option loaded\n"); } break; default: - memcpy((char*)ia_cmds->buf, (char*)ia_cmds->maddr, ia_cmds->len); - ia_cmds->status = 0; + ia_cmds.status = 0; break; } } @@ -2896,7 +2905,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { if (!iavcc->txing) { printk("discard packet on closed VC\n"); if (vcc->pop) vcc->pop(vcc, skb); - else dev_kfree_skb(skb); + else dev_kfree_skb_any(skb); } if (skb->len > iadev->tx_buf_sz - 8) { @@ -2904,7 +2913,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { if (vcc->pop) vcc->pop(vcc, skb); else - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return 0; } if ((u32)skb->data & 3) { @@ -2912,7 +2921,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { if (vcc->pop) vcc->pop(vcc, skb); else - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return 0; } /* Get a descriptor number from our free descriptor queue @@ -2929,11 +2938,11 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { if ((desc == 0) || (desc > iadev->num_tx_desc)) { IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);) - vcc->stats->tx++; + atomic_inc(&vcc->stats->tx); if (vcc->pop) vcc->pop(vcc, skb); else - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return 0; /* return SUCCESS */ } @@ -3038,14 +3047,14 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ATM_DESC(skb) = vcc->vci; skb_queue_tail(&iadev->tx_dma_q, skb); - vcc->stats->tx++; + atomic_inc(&vcc->stats->tx); iadev->tx_pkt_cnt++; /* Increment transaction counter */ writel(2, iadev->dma+IPHASE5575_TX_COUNTER); #if 0 /* add flow control logic */ - if (vcc->stats->tx % 20 == 0) { + if (atomic_read(&vcc->stats->tx) % 20 == 0) { if (iavcc->vc_desc_cnt > 10) { vcc->tx_quota = vcc->tx_quota * 3 / 4; printk("Tx1: vcc->tx_quota = %d \n", (u32)vcc->tx_quota ); @@ -3074,12 +3083,12 @@ static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb) { if (!skb) printk(KERN_CRIT "null skb in ia_send\n"); - else dev_kfree_skb(skb); + else dev_kfree_skb_any(skb); return -EINVAL; } spin_lock_irqsave(&iadev->tx_lock, flags); - if ((vcc->flags & ATM_VF_READY) == 0){ - dev_kfree_skb(skb); + if (!test_bit(ATM_VF_READY,&vcc->flags)){ + dev_kfree_skb_any(skb); spin_unlock_irqrestore(&iadev->tx_lock, flags); return -EINVAL; } @@ -3197,7 +3206,7 @@ __initfunc(int ia_detect(void)) IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n", iadev->pci->bus->number, PCI_SLOT(iadev->pci->devfn), PCI_FUNC(iadev->pci->devfn));) - dev = atm_dev_register(DEV_LABEL, &ops, -1, 0); + dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); if (!dev) break; IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", dev->number);) diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 3e4930fdd138..767fd75fb9d7 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -37,8 +37,10 @@ #include #include #include +#include #include #include +#include #include "nicstar.h" #include "nicstarmac.h" #ifdef CONFIG_ATM_NICSTAR_USE_SUNI @@ -284,7 +286,7 @@ void cleanup_module(void) card = cards[i]; #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 - if (card->max_pcr == IDT_25_PCR) { + if (card->max_pcr == ATM_25_PCR) { idt77105_stop(card->atmdev); } #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ @@ -311,7 +313,7 @@ void cleanup_module(void) PRINTK("nicstar%d: freeing %d huge buffers.\n", i, card->hbpool.count); while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) { - kfree_skb(hb); + dev_kfree_skb_any(hb); j++; } PRINTK("nicstar%d: %d huge buffers freed.\n", i, j); @@ -319,14 +321,14 @@ void cleanup_module(void) PRINTK("nicstar%d: freeing %d iovec buffers.\n", i, card->iovpool.count); while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) { - kfree_skb(iovb); + dev_kfree_skb_any(iovb); j++; } PRINTK("nicstar%d: %d iovec buffers freed.\n", i, j); while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) - kfree_skb(lb); + dev_kfree_skb_any(lb); while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) - kfree_skb(sb); + dev_kfree_skb_any(sb); free_scq(card->scq0, NULL); for (j = 0; j < NS_FRSCD_NUM; j++) { @@ -547,7 +549,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev) switch(data) { case 0x00000009: printk("nicstar%d: PHY seems to be 25 Mbps.\n", i); - card->max_pcr = IDT_25_PCR; + card->max_pcr = ATM_25_PCR; while(CMD_BUSY(card)); writel(0x00000008, card->membase + DR0); writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD); @@ -857,7 +859,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev) card->efbie = 1; /* Register device */ - card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, 0UL); + card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL); if (card->atmdev == NULL) { printk("nicstar%d: can't register device.\n", i); @@ -891,7 +893,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev) #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 - if (card->max_pcr == IDT_25_PCR) { + if (card->max_pcr == ATM_25_PCR) { idt77105_init(card->atmdev); /* Note that for the IDT77105 PHY we don't need the awful * module count hack that the SUNI needs because we can @@ -936,26 +938,26 @@ static void ns_init_card_error(ns_dev *card, int error) { struct sk_buff *iovb; while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) - kfree_skb(iovb); + dev_kfree_skb_any(iovb); } if (error >= 15) { struct sk_buff *sb; while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) - kfree_skb(sb); + dev_kfree_skb_any(sb); free_scq(card->scq0, NULL); } if (error >= 14) { struct sk_buff *lb; while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) - kfree_skb(lb); + dev_kfree_skb_any(lb); } if (error >= 13) { struct sk_buff *hb; while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) - kfree_skb(hb); + dev_kfree_skb_any(hb); } if (error >= 12) { @@ -1039,7 +1041,7 @@ static void free_scq(scq_info *scq, struct atm_vcc *vcc) if (vcc->pop != NULL) vcc->pop(vcc, scq->skb[i]); else - dev_kfree_skb(scq->skb[i]); + dev_kfree_skb_any(scq->skb[i]); } } else /* vcc must be != NULL */ @@ -1048,7 +1050,7 @@ static void free_scq(scq_info *scq, struct atm_vcc *vcc) { printk("nicstar: free_scq() called with vcc == NULL for fixed rate scq."); for (i = 0; i < scq->num_entries; i++) - dev_kfree_skb(scq->skb[i]); + dev_kfree_skb_any(scq->skb[i]); } else for (i = 0; i < scq->num_entries; i++) @@ -1058,7 +1060,7 @@ static void free_scq(scq_info *scq, struct atm_vcc *vcc) if (vcc->pop != NULL) vcc->pop(vcc, scq->skb[i]); else - dev_kfree_skb(scq->skb[i]); + dev_kfree_skb_any(scq->skb[i]); } } } @@ -1130,9 +1132,9 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, if (card->sbfqc >= card->sbnr.max) { skb_unlink((struct sk_buff *) handle1); - kfree_skb((struct sk_buff *) handle1); + dev_kfree_skb_any((struct sk_buff *) handle1); skb_unlink((struct sk_buff *) handle2); - kfree_skb((struct sk_buff *) handle2); + dev_kfree_skb_any((struct sk_buff *) handle2); return; } else @@ -1143,9 +1145,9 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, if (card->lbfqc >= card->lbnr.max) { skb_unlink((struct sk_buff *) handle1); - kfree_skb((struct sk_buff *) handle1); + dev_kfree_skb_any((struct sk_buff *) handle1); skb_unlink((struct sk_buff *) handle2); - kfree_skb((struct sk_buff *) handle2); + dev_kfree_skb_any((struct sk_buff *) handle2); return; } else @@ -1420,16 +1422,16 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) return -EINVAL; } - vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&vcc->flags); /* NOTE: You are not allowed to modify an open connection's QOS. To change that, remove the ATM_VF_PARTIAL flag checking. There may be other changes needed to do that. */ - if (!(vcc->flags & ATM_VF_PARTIAL)) + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { scq_info *scq; - vcc->flags |= ATM_VF_PARTIAL; + set_bit(ATM_VF_PARTIAL,&vcc->flags); if (vcc->qos.txtp.traffic_class == ATM_CBR) { /* Check requested cell rate and availability of SCD */ @@ -1438,7 +1440,8 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) { PRINTK("nicstar%d: trying to open a CBR vc with cell rate = 0 \n", card->index); - vcc->flags &= ~(ATM_VF_ADDR | ATM_VF_PARTIAL); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); return -EINVAL; } @@ -1461,7 +1464,8 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0) { PRINTK("nicstar%d: no CBR bandwidth free.\n", card->index); - vcc->flags &= ~(ATM_VF_ADDR | ATM_VF_PARTIAL); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); return -EINVAL; } } @@ -1469,14 +1473,16 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) if (n == 0) { printk("nicstar%d: selected bandwidth < granularity.\n", card->index); - vcc->flags &= ~(ATM_VF_ADDR | ATM_VF_PARTIAL); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); return -EINVAL; } if (n > (card->tst_free_entries - NS_TST_RESERVED)) { PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index); - vcc->flags &= ~(ATM_VF_ADDR | ATM_VF_PARTIAL); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); return -EINVAL; } else @@ -1495,7 +1501,8 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) { PRINTK("nicstar%d: no SCD available for CBR channel.\n", card->index); card->tst_free_entries += n; - vcc->flags &= ~(ATM_VF_ADDR | ATM_VF_PARTIAL); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); return -EBUSY; } @@ -1507,7 +1514,8 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index); card->scd2vc[frscdi] = NULL; card->tst_free_entries += n; - vcc->flags &= ~(ATM_VF_ADDR | ATM_VF_PARTIAL); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); return -ENOMEM; } vc->scq = scq; @@ -1553,7 +1561,7 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci) } - vcc->flags |= ATM_VF_READY; + set_bit(ATM_VF_READY,&vcc->flags); MOD_INC_USE_COUNT; return 0; } @@ -1572,7 +1580,7 @@ static void ns_close(struct atm_vcc *vcc) PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index, (int) vcc->vpi, vcc->vci); - vcc->flags &= ~(ATM_VF_READY); + clear_bit(ATM_VF_READY,&vcc->flags); if (vcc->qos.rxtp.traffic_class != ATM_NONE) { @@ -1681,7 +1689,8 @@ static void ns_close(struct atm_vcc *vcc) } vcc->dev_data = NULL; - vcc->flags &= ~(ATM_VF_PARTIAL | ATM_VF_ADDR); + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_ADDR,&vcc->flags); MOD_DEC_USE_COUNT; #ifdef RX_DEBUG @@ -1778,32 +1787,32 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) if ((vc = (vc_map *) vcc->dev_data) == NULL) { printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", card->index); - vcc->stats->tx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); return -EINVAL; } if (!vc->tx) { printk("nicstar%d: Trying to transmit on a non-tx VC.\n", card->index); - vcc->stats->tx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); return -EINVAL; } if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) { printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", card->index); - vcc->stats->tx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); return -EINVAL; } if (ATM_SKB(skb)->iovcnt != 0) { printk("nicstar%d: No scatter-gather yet.\n", card->index); - vcc->stats->tx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); return -EINVAL; } @@ -1847,11 +1856,11 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) if (push_scqe(card, vc, scq, &scqe, skb) != 0) { - vcc->stats->tx_err++; - dev_kfree_skb(skb); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); return -EIO; } - vcc->stats->tx++; + atomic_inc(&vcc->stats->tx); return 0; } @@ -2071,7 +2080,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos) if (vcc->pop != NULL) vcc->pop(vcc, skb); else - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); scq->skb[i] = NULL; } if (++i == scq->num_entries) @@ -2155,15 +2164,15 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) { printk("nicstar%d: Can't allocate buffers for aal0.\n", card->index); - vcc->stats->rx_drop += i; + atomic_add(i,&vcc->stats->rx_drop); break; } if (!atm_charge(vcc, sb->truesize)) { RXPRINTK("nicstar%d: atm_charge() dropped aal0 packets.\n", card->index); - vcc->stats->rx_drop += i - 1; /* already increased by 1 */ - kfree_skb(sb); + atomic_add(i-1,&vcc->stats->rx_drop); /* already increased by 1 */ + dev_kfree_skb_any(sb); break; } /* Rebuild the header */ @@ -2177,7 +2186,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) ATM_SKB(sb)->vcc = vcc; sb->stamp = xtime; vcc->push(vcc, sb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); cell += ATM_CELL_PAYLOAD; } @@ -2196,7 +2205,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) if (iovb == NULL) { printk("nicstar%d: Out of iovec buffers.\n", card->index); - vcc->stats->rx_drop++; + atomic_inc(&vcc->stats->rx_drop); recycle_rx_buf(card, skb); return; } @@ -2223,7 +2232,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) else if (ATM_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) { printk("nicstar%d: received too big AAL5 SDU.\n", card->index); - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS); ATM_SKB(iovb)->iovcnt = 0; iovb->len = 0; @@ -2242,7 +2251,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) printk("nicstar%d: Expected a small buffer, and this is not one.\n", card->index); which_list(card, skb); - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); recycle_rx_buf(card, skb); vc->rx_iov = NULL; recycle_iov_buf(card, iovb); @@ -2256,7 +2265,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) printk("nicstar%d: Expected a large buffer, and this is not one.\n", card->index); which_list(card, skb); - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, ATM_SKB(iovb)->iovcnt); vc->rx_iov = NULL; @@ -2280,7 +2289,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) printk(" - PDU size mismatch.\n"); else printk(".\n"); - vcc->stats->rx_err++; + atomic_inc(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, ATM_SKB(iovb)->iovcnt); vc->rx_iov = NULL; @@ -2308,7 +2317,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) ATM_SKB(skb)->vcc = vcc; skb->stamp = xtime; vcc->push(vcc, skb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } } else if (ATM_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */ @@ -2335,7 +2344,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) ATM_SKB(sb)->vcc = vcc; sb->stamp = xtime; vcc->push(vcc, sb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } push_rxbufs(card, BUF_LG, (u32) skb, @@ -2361,7 +2370,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) ATM_SKB(skb)->vcc = vcc; skb->stamp = xtime; vcc->push(vcc, skb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), @@ -2384,7 +2393,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) if (hb == NULL) { printk("nicstar%d: Out of huge buffers.\n", card->index); - vcc->stats->rx_drop++; + atomic_inc(&vcc->stats->rx_drop); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, ATM_SKB(iovb)->iovcnt); vc->rx_iov = NULL; @@ -2431,7 +2440,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) card->hbpool.count++; } else - kfree_skb(hb); + dev_kfree_skb_any(hb); } else { @@ -2467,7 +2476,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) #endif /* NS_USE_DESTRUCTORS */ hb->stamp = xtime; vcc->push(vcc, hb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } } @@ -2556,7 +2565,7 @@ static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb) else { printk("nicstar%d: What kind of rx buffer is this?\n", card->index); - kfree_skb(skb); + dev_kfree_skb_any(skb); } } @@ -2578,7 +2587,7 @@ static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count) else { printk("nicstar%d: What kind of rx buffer is this?\n", card->index); - kfree_skb(skb); + dev_kfree_skb_any(skb); } } } @@ -2593,7 +2602,7 @@ static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb) card->iovpool.count++; } else - kfree_skb(iovb); + dev_kfree_skb_any(iovb); } @@ -2700,7 +2709,7 @@ static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page) /* Dump 25.6 Mbps PHY registers */ /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it here just in case it's needed for debugging. */ - if (card->max_pcr == IDT_25_PCR && !left--) + if (card->max_pcr == ATM_25_PCR && !left--) { u32 phy_regs[4]; u32 i; @@ -2787,7 +2796,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) return -EFAULT; case NS_SETBUFLEV: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&pl, (pool_levels *) arg, sizeof(pl))) return -EFAULT; @@ -2836,7 +2845,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) return 0; case NS_ADJBUFLEV: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; btype = (int) arg; /* an int is the same size as a pointer */ switch (btype) @@ -2882,7 +2891,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) printk("nicstar%d: huge buffer count inconsistent.\n", card->index); else - kfree_skb(hb); + dev_kfree_skb_any(hb); } while (card->hbpool.count < card->hbnr.init) @@ -2912,7 +2921,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) printk("nicstar%d: iovec buffer count inconsistent.\n", card->index); else - kfree_skb(iovb); + dev_kfree_skb_any(iovb); } while (card->iovpool.count < card->iovnr.init) diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h index 61b89efe0f4c..4e90650c01dd 100644 --- a/drivers/atm/nicstar.h +++ b/drivers/atm/nicstar.h @@ -100,8 +100,6 @@ #define NS_IOREMAP_SIZE 4096 -#define IDT_25_PCR ((25600000 / 8 - 8000) / 54) - #define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */ #define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */ diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c index 7335bbb32f9f..0de6e8eadcf8 100644 --- a/drivers/atm/suni.c +++ b/drivers/atm/suni.c @@ -1,4 +1,4 @@ -/* drivers/atm/suni.c - PMC SUNI (PHY) driver */ +/* drivers/atm/suni.c - PMC PM5346 SUNI (PHY) driver */ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ @@ -18,6 +18,7 @@ #include #include #include +#include #include "suni.h" @@ -30,8 +31,8 @@ struct suni_priv { - struct sonet_stats sonet_stats; /* link diagnostics */ - unsigned char loop_mode; /* loopback mode */ + struct k_sonet_stats sonet_stats; /* link diagnostics */ + int loop_mode; /* loopback mode */ struct atm_dev *dev; /* device back-pointer */ struct suni_priv *next; /* next SUNI */ }; @@ -46,69 +47,62 @@ struct suni_priv { static struct timer_list poll_timer; -static int start_timer = 1; static struct suni_priv *sunis = NULL; +static spinlock_t sunis_lock = SPIN_LOCK_UNLOCKED; -static void suni_hz(unsigned long dummy) +#define ADD_LIMITED(s,v) \ + atomic_add((v),&stats->s); \ + if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX); + + +static void suni_hz(unsigned long from_timer) { struct suni_priv *walk; struct atm_dev *dev; - struct sonet_stats *stats; + struct k_sonet_stats *stats; for (walk = sunis; walk; walk = walk->next) { dev = walk->dev; stats = &walk->sonet_stats; PUT(0,MRI); /* latch counters */ udelay(1); - stats->section_bip += (GET(RSOP_SBL) & 0xff) | - ((GET(RSOP_SBM) & 0xff) << 8); - if (stats->section_bip < 0) stats->section_bip = LONG_MAX; - stats->line_bip += (GET(RLOP_LBL) & 0xff) | + ADD_LIMITED(section_bip,(GET(RSOP_SBL) & 0xff) | + ((GET(RSOP_SBM) & 0xff) << 8)); + ADD_LIMITED(line_bip,(GET(RLOP_LBL) & 0xff) | ((GET(RLOP_LB) & 0xff) << 8) | - ((GET(RLOP_LBM) & 0xf) << 16); - if (stats->line_bip < 0) stats->line_bip = LONG_MAX; - stats->path_bip += (GET(RPOP_PBL) & 0xff) | - ((GET(RPOP_PBM) & 0xff) << 8); - if (stats->path_bip < 0) stats->path_bip = LONG_MAX; - stats->line_febe += (GET(RLOP_LFL) & 0xff) | + ((GET(RLOP_LBM) & 0xf) << 16)); + ADD_LIMITED(path_bip,(GET(RPOP_PBL) & 0xff) | + ((GET(RPOP_PBM) & 0xff) << 8)); + ADD_LIMITED(line_febe,(GET(RLOP_LFL) & 0xff) | ((GET(RLOP_LF) & 0xff) << 8) | - ((GET(RLOP_LFM) & 0xf) << 16); - if (stats->line_febe < 0) stats->line_febe = LONG_MAX; - stats->path_febe += (GET(RPOP_PFL) & 0xff) | - ((GET(RPOP_PFM) & 0xff) << 8); - if (stats->path_febe < 0) stats->path_febe = LONG_MAX; - stats->corr_hcs += GET(RACP_CHEC) & 0xff; - if (stats->corr_hcs < 0) stats->corr_hcs = LONG_MAX; - stats->uncorr_hcs += GET(RACP_UHEC) & 0xff; - if (stats->uncorr_hcs < 0) stats->uncorr_hcs = LONG_MAX; - stats->rx_cells += (GET(RACP_RCCL) & 0xff) | + ((GET(RLOP_LFM) & 0xf) << 16)); + ADD_LIMITED(path_febe,(GET(RPOP_PFL) & 0xff) | + ((GET(RPOP_PFM) & 0xff) << 8)); + ADD_LIMITED(corr_hcs,GET(RACP_CHEC) & 0xff); + ADD_LIMITED(uncorr_hcs,GET(RACP_UHEC) & 0xff); + ADD_LIMITED(rx_cells,(GET(RACP_RCCL) & 0xff) | ((GET(RACP_RCC) & 0xff) << 8) | - ((GET(RACP_RCCM) & 7) << 16); - if (stats->rx_cells < 0) stats->rx_cells = LONG_MAX; - stats->tx_cells += (GET(TACP_TCCL) & 0xff) | + ((GET(RACP_RCCM) & 7) << 16)); + ADD_LIMITED(tx_cells,(GET(TACP_TCCL) & 0xff) | ((GET(TACP_TCC) & 0xff) << 8) | - ((GET(TACP_TCCM) & 7) << 16); - if (stats->tx_cells < 0) stats->tx_cells = LONG_MAX; + ((GET(TACP_TCCM) & 7) << 16)); } - if (!start_timer) mod_timer(&poll_timer,jiffies+HZ); + if (from_timer) mod_timer(&poll_timer,jiffies+HZ); } +#undef ADD_LIMITED + + static int fetch_stats(struct atm_dev *dev,struct sonet_stats *arg,int zero) { - unsigned long flags; - int error; - - error = 0; - save_flags(flags); - cli(); - if (arg) - error = copy_to_user(arg,&PRIV(dev)->sonet_stats, - sizeof(struct sonet_stats)); - if (zero && !error) - memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); - restore_flags(flags); + struct sonet_stats tmp; + int error = 0; + + sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp); + if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); + if (zero && !error) sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp); return error ? -EFAULT : 0; } @@ -158,6 +152,29 @@ static int get_diag(struct atm_dev *dev,void *arg) } +static int set_loopback(struct atm_dev *dev,int mode) +{ + unsigned char control; + + control = GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE); + switch (mode) { + case ATM_LM_NONE: + break; + case ATM_LM_LOC_PHY: + control |= SUNI_MCT_DLE; + break; + case ATM_LM_RMT_PHY: + control |= SUNI_MCT_LLE; + break; + default: + return -EINVAL; + } + PUT(control,MCT); + PRIV(dev)->loop_mode = mode; + return 0; +} + + static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) { switch (cmd) { @@ -172,7 +189,6 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) case SONET_GETDIAG: return get_diag(dev,arg); case SONET_SETFRAMING: - if (!capable(CAP_NET_ADMIN)) return -EPERM; if (arg != SONET_FRAME_SONET) return -EINVAL; return 0; case SONET_GETFRAMING: @@ -180,23 +196,14 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) -EFAULT : 0; case SONET_GETFRSENSE: return -EINVAL; - case SUNI_SETLOOP: - { - int int_arg = (int) (long) arg; - - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (int_arg < 0 || int_arg > SUNI_LM_LOOP) - return -EINVAL; - PUT((GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE)) - | (int_arg == SUNI_LM_DIAG ? SUNI_MCT_DLE : - 0) | (int_arg == SUNI_LM_LOOP ? - SUNI_MCT_LLE : 0),MCT); - PRIV(dev)->loop_mode = int_arg; - return 0; - } - case SUNI_GETLOOP: + case ATM_SETLOOP: + return set_loopback(dev,(int) (long) arg); + case ATM_GETLOOP: return put_user(PRIV(dev)->loop_mode,(int *) arg) ? -EFAULT : 0; + case ATM_QUERYLOOP: + return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, + (int *) arg) ? -EFAULT : 0; default: return -ENOIOCTLCMD; } @@ -221,33 +228,31 @@ static void suni_int(struct atm_dev *dev) static int suni_start(struct atm_dev *dev) { unsigned long flags; + int first; if (!(PRIV(dev) = kmalloc(sizeof(struct suni_priv),GFP_KERNEL))) return -ENOMEM; PRIV(dev)->dev = dev; - save_flags(flags); - cli(); + spin_lock_irqsave(&sunis_lock,flags); + first = !sunis; PRIV(dev)->next = sunis; sunis = PRIV(dev); - restore_flags(flags); - memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); + spin_unlock_irqrestore(&sunis_lock,flags); + memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats)); PUT(GET(RSOP_CIE) | SUNI_RSOP_CIE_LOSE,RSOP_CIE); /* interrupt on loss of signal */ poll_los(dev); /* ... and clear SUNI interrupts */ if (dev->signal == ATM_PHY_SIG_LOST) printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type, dev->number); - PRIV(dev)->loop_mode = SUNI_LM_NONE; + PRIV(dev)->loop_mode = ATM_LM_NONE; suni_hz(0); /* clear SUNI counters */ (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ - cli(); - if (!start_timer) restore_flags(flags); - else { - start_timer = 0; - restore_flags(flags); + if (first) { init_timer(&poll_timer); poll_timer.expires = jiffies+HZ; poll_timer.function = suni_hz; + poll_timer.data = 1; #if 0 printk(KERN_DEBUG "[u] p=0x%lx,n=0x%lx\n",(unsigned long) poll_timer.prev, (unsigned long) poll_timer.next); @@ -258,10 +263,28 @@ printk(KERN_DEBUG "[u] p=0x%lx,n=0x%lx\n",(unsigned long) poll_timer.prev, } +static int suni_stop(struct atm_dev *dev) +{ + struct suni_priv **walk; + unsigned long flags; + + /* let SAR driver worry about stopping interrupts */ + spin_lock_irqsave(&sunis_lock,flags); + for (walk = &sunis; *walk != PRIV(dev); + walk = &PRIV((*walk)->dev)->next); + *walk = PRIV((*walk)->dev)->next; + if (!sunis) del_timer_sync(&poll_timer); + spin_unlock_irqrestore(&sunis_lock,flags); + kfree(PRIV(dev)); + return 0; +} + + static const struct atmphy_ops suni_ops = { - suni_start, - suni_ioctl, - suni_int + start: suni_start, + ioctl: suni_ioctl, + interrupt: suni_int, + stop: suni_stop, }; diff --git a/drivers/atm/suni.h b/drivers/atm/suni.h index f72cdc7beebb..ae6d39abbddf 100644 --- a/drivers/atm/suni.h +++ b/drivers/atm/suni.h @@ -1,6 +1,6 @@ -/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */ +/* drivers/atm/suni.h - PMC PM5346 SUNI (PHY) declarations */ -/* Written 1995,1998 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #ifndef DRIVER_ATM_SUNI_H diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c index 36fd70b170e4..7c5f5757935d 100644 --- a/drivers/atm/uPD98402.c +++ b/drivers/atm/uPD98402.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "uPD98402.h" @@ -23,8 +24,9 @@ struct uPD98402_priv { - struct sonet_stats sonet_stats; /* link diagnostics */ + struct k_sonet_stats sonet_stats;/* link diagnostics */ unsigned char framing; /* SONET/SDH framing */ + int loop_mode; /* loopback mode */ }; @@ -36,23 +38,18 @@ struct uPD98402_priv { static int fetch_stats(struct atm_dev *dev,struct sonet_stats *arg,int zero) { - unsigned long flags; - int error; + struct sonet_stats tmp; + int error = 0; - error = 0; - save_flags(flags); - cli(); - PRIV(dev)->sonet_stats.uncorr_hcs += GET(HECCT); - if (arg) - error = copy_to_user(arg,&PRIV(dev)->sonet_stats, - sizeof(struct sonet_stats)); + atomic_add(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs); + sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp); + if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); if (zero && !error) { - memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); - PRIV(dev)->sonet_stats.corr_hcs = -1; - PRIV(dev)->sonet_stats.tx_cells = -1; - PRIV(dev)->sonet_stats.rx_cells = -1; + /* unused fields are reported as -1, but we must not "adjust" + them */ + tmp.corr_hcs = tmp.tx_cells = tmp.rx_cells = 0; + sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp); } - restore_flags(flags); return error ? -EFAULT : 0; } @@ -102,6 +99,39 @@ static int get_sense(struct atm_dev *dev,u8 *arg) } +static int set_loopback(struct atm_dev *dev,int mode) +{ + unsigned char mode_reg; + + mode_reg = GET(MDR) & ~(uPD98402_MDR_TPLP | uPD98402_MDR_ALP | + uPD98402_MDR_RPLP); + switch (__ATM_LM_XTLOC(mode)) { + case __ATM_LM_NONE: + break; + case __ATM_LM_PHY: + mode_reg |= uPD98402_MDR_TPLP; + break; + case __ATM_LM_ATM: + mode_reg |= uPD98402_MDR_ALP; + break; + default: + return -EINVAL; + } + switch (__ATM_LM_XTRMT(mode)) { + case __ATM_LM_NONE: + break; + case __ATM_LM_PHY: + mode_reg |= uPD98402_MDR_RPLP; + break; + default: + return -EINVAL; + } + PUT(mode_reg,MDR); + PRIV(dev)->loop_mode = mode; + return 0; +} + + static int uPD98402_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) { switch (cmd) { @@ -117,35 +147,42 @@ static int uPD98402_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) -EFAULT : 0; case SONET_GETFRSENSE: return get_sense(dev,arg); + case ATM_SETLOOP: + return set_loopback(dev,(int) (long) arg); + case ATM_GETLOOP: + return put_user(PRIV(dev)->loop_mode,(int *) arg) ? + -EFAULT : 0; + case ATM_QUERYLOOP: + return put_user(ATM_LM_LOC_PHY | ATM_LM_LOC_ATM | + ATM_LM_RMT_PHY,(int *) arg) ? -EFAULT : 0; default: - return -ENOIOCTLCMD; + return -ENOIOCTLCMD; } } +#define ADD_LIMITED(s,v) \ + { atomic_add(GET(v),&PRIV(dev)->sonet_stats.s); \ + if (atomic_read(&PRIV(dev)->sonet_stats.s) < 0) \ + atomic_set(&PRIV(dev)->sonet_stats.s,INT_MAX); } + + static void stat_event(struct atm_dev *dev) { unsigned char events; events = GET(PCR); - if (events & uPD98402_PFM_PFEB) - if ((PRIV(dev)->sonet_stats.path_febe += GET(PFECB)) < 0) - PRIV(dev)->sonet_stats.path_febe = LONG_MAX; - if (events & uPD98402_PFM_LFEB) - if ((PRIV(dev)->sonet_stats.line_febe += GET(LECCT)) < 0) - PRIV(dev)->sonet_stats.line_febe = LONG_MAX; - if (events & uPD98402_PFM_B3E) - if ((PRIV(dev)->sonet_stats.path_bip += GET(B3ECT)) < 0) - PRIV(dev)->sonet_stats.path_bip = LONG_MAX; - if (events & uPD98402_PFM_B2E) - if ((PRIV(dev)->sonet_stats.line_bip += GET(B2ECT)) < 0) - PRIV(dev)->sonet_stats.line_bip = LONG_MAX; - if (events & uPD98402_PFM_B1E) - if ((PRIV(dev)->sonet_stats.section_bip += GET(B1ECT)) < 0) - PRIV(dev)->sonet_stats.section_bip = LONG_MAX; + if (events & uPD98402_PFM_PFEB) ADD_LIMITED(path_febe,PFECB); + if (events & uPD98402_PFM_LFEB) ADD_LIMITED(line_febe,LECCT); + if (events & uPD98402_PFM_B3E) ADD_LIMITED(path_bip,B3ECT); + if (events & uPD98402_PFM_B2E) ADD_LIMITED(line_bip,B2ECT); + if (events & uPD98402_PFM_B1E) ADD_LIMITED(section_bip,B1ECT); } +#undef ADD_LIMITED + + static void uPD98402_int(struct atm_dev *dev) { static unsigned long silence = 0; @@ -158,7 +195,8 @@ static void uPD98402_int(struct atm_dev *dev) if (reason & uPD98402_INT_PFM) stat_event(dev); if (reason & uPD98402_INT_PCO) { (void) GET(PCOCR); /* clear interrupt cause */ - PRIV(dev)->sonet_stats.uncorr_hcs += GET(HECCT); + atomic_add(GET(HECCT), + &PRIV(dev)->sonet_stats.uncorr_hcs); } if ((reason & uPD98402_INT_RFO) && (time_after(jiffies, silence) || silence == 0)) { @@ -172,10 +210,10 @@ static void uPD98402_int(struct atm_dev *dev) static int uPD98402_start(struct atm_dev *dev) { -DPRINTK("phy_start\n"); + DPRINTK("phy_start\n"); if (!(PRIV(dev) = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL))) return -ENOMEM; - memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); + memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats)); (void) GET(PCR); /* clear performance events */ PUT(uPD98402_PFM_FJ,PCMR); /* ignore frequency adj */ (void) GET(PCOCR); /* clear overflows */ @@ -184,15 +222,26 @@ DPRINTK("phy_start\n"); PUT(~(uPD98402_INT_PFM | uPD98402_INT_ALM | uPD98402_INT_RFO | uPD98402_INT_LOS),PIMR); /* enable them */ (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ + atomic_set(&PRIV(dev)->sonet_stats.corr_hcs,-1); + atomic_set(&PRIV(dev)->sonet_stats.tx_cells,-1); + atomic_set(&PRIV(dev)->sonet_stats.rx_cells,-1); return 0; } +static int uPD98402_stop(struct atm_dev *dev) +{ + /* let SAR driver worry about stopping interrupts */ + kfree(PRIV(dev)); + return 0; +} + static const struct atmphy_ops uPD98402_ops = { - uPD98402_start, - uPD98402_ioctl, /* no ioctl yet */ - uPD98402_int + start: uPD98402_start, + ioctl: uPD98402_ioctl, + interrupt: uPD98402_int, + stop: uPD98402_stop, }; diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 26c8c9d90b0d..1b68f5529969 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -21,10 +21,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "uPD98401.h" @@ -637,7 +639,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); } if (!size) { dev_kfree_skb_irq(skb); - if (vcc) vcc->stats->rx_err++; + if (vcc) atomic_inc(&vcc->stats->rx_err); continue; } if (!atm_charge(vcc,skb->truesize)) { @@ -647,7 +649,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); skb->len = size; ATM_SKB(skb)->vcc = vcc; vcc->push(vcc,skb); - vcc->stats->rx++; + atomic_inc(&vcc->stats->rx); } zout(pos & 0xffff,MTA(mbx)); #if 0 /* probably a stupid idea */ @@ -914,7 +916,7 @@ if (*ZATM_PRV_DSC(skb) != (uPD98401_TXPD_V | uPD98401_TXPD_DP | skb_queue_head(&zatm_vcc->backlog,skb); break; } - vcc->stats->tx++; + atomic_inc(&vcc->stats->tx); wake_up(&zatm_vcc->tx_wait); } @@ -1537,7 +1539,7 @@ static void zatm_close(struct atm_vcc *vcc) { DPRINTK(">zatm_close\n"); if (!ZATM_VCC(vcc)) return; - vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); close_rx(vcc); EVENT("close_tx\n",0,0); close_tx(vcc); @@ -1545,7 +1547,7 @@ static void zatm_close(struct atm_vcc *vcc) /* deallocate memory */ kfree(ZATM_VCC(vcc)); ZATM_VCC(vcc) = NULL; - vcc->flags &= ~ATM_VF_ADDR; + clear_bit(ATM_VF_ADDR,&vcc->flags); } @@ -1557,20 +1559,20 @@ static int zatm_open(struct atm_vcc *vcc,short vpi,int vci) DPRINTK(">zatm_open\n"); zatm_dev = ZATM_DEV(vcc->dev); - if (!(vcc->flags & ATM_VF_PARTIAL)) ZATM_VCC(vcc) = NULL; + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ZATM_VCC(vcc) = NULL; error = atm_find_ci(vcc,&vpi,&vci); if (error) return error; vcc->vpi = vpi; vcc->vci = vci; if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) - vcc->flags |= ATM_VF_ADDR; + set_bit(ATM_VF_ADDR,&vcc->flags); if (vcc->qos.aal != ATM_AAL5) return -EINVAL; /* @@@ AAL0 */ DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi, vcc->vci); - if (!(vcc->flags & ATM_VF_PARTIAL)) { + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { zatm_vcc = kmalloc(sizeof(struct zatm_vcc),GFP_KERNEL); if (!zatm_vcc) { - vcc->flags &= ~ATM_VF_ADDR; + clear_bit(ATM_VF_ADDR,&vcc->flags); return -ENOMEM; } ZATM_VCC(vcc) = zatm_vcc; @@ -1593,7 +1595,7 @@ static int zatm_open(struct atm_vcc *vcc,short vpi,int vci) zatm_close(vcc); return error; } - vcc->flags |= ATM_VF_READY; + set_bit(ATM_VF_READY,&vcc->flags); return 0; } @@ -1733,7 +1735,7 @@ static int zatm_send(struct atm_vcc *vcc,struct sk_buff *skb) int error; EVENT(">zatm_send 0x%lx\n",(unsigned long) skb,0); - if (!ZATM_VCC(vcc)->tx_chan || !(vcc->flags & ATM_VF_READY)) { + if (!ZATM_VCC(vcc)->tx_chan || !test_bit(ATM_VF_READY,&vcc->flags)) { if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); return -EINVAL; @@ -1809,7 +1811,7 @@ int __init zatm_detect(void) while ((pci_dev = pci_find_device(PCI_VENDOR_ID_ZEITNET,type ? PCI_DEVICE_ID_ZEITNET_1225 : PCI_DEVICE_ID_ZEITNET_1221, pci_dev))) { - dev = atm_dev_register(DEV_LABEL,&ops,-1,0); + dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL); if (!dev) break; zatm_dev->pci_dev = pci_dev; ZATM_DEV(dev) = zatm_dev; diff --git a/drivers/char/atixlmouse.c b/drivers/char/atixlmouse.c index 4c4b6ccf95b6..4bc4b64ff00f 100644 --- a/drivers/char/atixlmouse.c +++ b/drivers/char/atixlmouse.c @@ -117,7 +117,7 @@ static int __init atixl_busmouse_init(void) * may race another module load of the same I/O */ - if (request_region(ATIXL_MSE_DATA_PORT, 3, "atixlmouse")) + if (!request_region(ATIXL_MSE_DATA_PORT, 3, "atixlmouse")) return -EIO; a = inb( ATIXL_MSE_SIGNATURE_PORT ); /* Get signature */ diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index f2314a2f7e69..04ff370f35a6 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -48,8 +48,6 @@ */ /*#define BROKEN_MOUSE*/ -extern int sun_mouse_init(void); - struct busmouse_data { struct miscdevice miscdev; struct busmouse *ops; @@ -446,27 +444,8 @@ fail: return err; } -int __init bus_mouse_init(void) -{ -#ifdef CONFIG_SUN_MOUSE - sun_mouse_init(); -#endif - return 0; -} - EXPORT_SYMBOL(busmouse_add_movementbuttons); EXPORT_SYMBOL(busmouse_add_movement); EXPORT_SYMBOL(busmouse_add_buttons); EXPORT_SYMBOL(register_busmouse); EXPORT_SYMBOL(unregister_busmouse); - -#ifdef MODULE -int init_module(void) -{ - return bus_mouse_init(); -} - -void cleanup_module(void) -{ -} -#endif diff --git a/drivers/char/busmouse.h b/drivers/char/busmouse.h index 3626334d945f..4ba7c9ce4a88 100644 --- a/drivers/char/busmouse.h +++ b/drivers/char/busmouse.h @@ -23,6 +23,4 @@ extern void busmouse_add_buttons(int mousedev, int clear, int eor); extern int register_busmouse(struct busmouse *ops); extern int unregister_busmouse(int mousedev); -extern int bus_mouse_init(void); - #endif diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 870cb50fb7b5..7cb29f93629a 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -224,9 +224,6 @@ EXPORT_SYMBOL(misc_deregister); int __init misc_init(void) { create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL); -#ifdef CONFIG_BUSMOUSE - bus_mouse_init(); -#endif #if defined CONFIG_82C710_MOUSE qpmouse_init(); #endif diff --git a/drivers/ieee1394/Config.in b/drivers/ieee1394/Config.in index 899add4900da..df0e3cfd2058 100644 --- a/drivers/ieee1394/Config.in +++ b/drivers/ieee1394/Config.in @@ -14,11 +14,12 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then fi dep_tristate 'Adaptec AIC-5800 (AHA-89xx) support' CONFIG_IEEE1394_AIC5800 $CONFIG_IEEE1394 - + dep_tristate 'OHCI (Open Host Controller Interface) support' CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394 dep_tristate 'Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394 + bool 'Excessive debugging output' CONFIG_IEEE1394_VERBOSEDEBUG fi endmenu fi diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c index 4ffe0faddbc5..a884f2a1c27c 100644 --- a/drivers/ieee1394/csr.c +++ b/drivers/ieee1394/csr.c @@ -14,6 +14,7 @@ #include "highlevel.h" +/* FIXME: this one won't work on little endian with big endian data */ static u16 csr_crc16(unsigned *data, int length) { int check=0, i; @@ -47,14 +48,18 @@ static void host_reset(struct hpsb_host *host) host->csr.state &= ~0x100; } - host->csr.topology_map[1]++; - host->csr.topology_map[2] = host->node_count << 16 | host->selfid_count; - host->csr.topology_map[0] = (host->selfid_count + 2) << 16 - | csr_crc16(host->csr.topology_map + 1, host->selfid_count + 2); - - /* FIXME - generate speed map */ - host->csr.speed_map[0] = 0x3f1 << 16 | csr_crc16(host->csr.speed_map+1, - 0x3f1); + host->csr.topology_map[1] = + cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1); + host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16 + | host->selfid_count); + host->csr.topology_map[0] = + cpu_to_be32((host->selfid_count + 2) << 16 + | csr_crc16(host->csr.topology_map + 1, + host->selfid_count + 2)); + + host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16 + | csr_crc16(host->csr.speed_map+1, + 0x3f1)); } @@ -78,8 +83,8 @@ static void add_host(struct hpsb_host *host) /* Read topology / speed maps and configuration ROM */ -static int read_maps(struct hpsb_host *host, quadlet_t *buffer, u64 addr, - unsigned int length) +static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, unsigned int length) { int csraddr = addr - CSR_REGISTER_BASE; const char *src; @@ -100,43 +105,11 @@ static int read_maps(struct hpsb_host *host, quadlet_t *buffer, u64 addr, return RCODE_COMPLETE; } -/* Read FCP register space */ -static int read_fcp(struct hpsb_host *host, quadlet_t *buffer, u64 addr, - unsigned int length) -{ - int csraddr = addr - CSR_REGISTER_BASE; - const char *src; - - if (csraddr + length > CSR_FCP_END) { - return RCODE_ADDRESS_ERROR; - } - src = ((char *)host->csr.fcp_data) + csraddr - CSR_FCP_COMMAND; - - memcpy(buffer, src, length); - return RCODE_COMPLETE; -} - -/* Write FCP register space */ -static int write_fcp(struct hpsb_host *host, quadlet_t *data, u64 addr, - unsigned int length) -{ - int csraddr = addr - CSR_REGISTER_BASE; - char *dest; - - if (csraddr + length > CSR_FCP_END) { - return RCODE_ADDRESS_ERROR; - } - dest = ((char *)host->csr.fcp_data) + csraddr - CSR_FCP_COMMAND; - - memcpy(dest, data, length); - return RCODE_COMPLETE; -} - #define out if (--length == 0) break -static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, - unsigned int length) +static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, + u64 addr, unsigned int length) { int csraddr = addr - CSR_REGISTER_BASE; int oldcycle; @@ -149,13 +122,13 @@ static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, switch (csraddr) { case CSR_STATE_CLEAR: - *(buf++) = host->csr.state; + *(buf++) = cpu_to_be32(host->csr.state); out; case CSR_STATE_SET: - *(buf++) = host->csr.state; + *(buf++) = cpu_to_be32(host->csr.state); out; case CSR_NODE_IDS: - *(buf++) = host->csr.node_ids; + *(buf++) = cpu_to_be32(host->csr.node_ids); out; case CSR_RESET_START: @@ -164,10 +137,10 @@ static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, /* address gap - handled by default below */ case CSR_SPLIT_TIMEOUT_HI: - *(buf++) = host->csr.split_timeout_hi; + *(buf++) = cpu_to_be32(host->csr.split_timeout_hi); out; case CSR_SPLIT_TIMEOUT_LO: - *(buf++) = host->csr.split_timeout_lo; + *(buf++) = cpu_to_be32(host->csr.split_timeout_lo); out; /* address gap */ @@ -182,7 +155,7 @@ static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, /* cycle time wrapped around */ host->csr.bus_time += 1 << 7; } - *(buf++) = host->csr.cycle_time; + *(buf++) = cpu_to_be32(host->csr.cycle_time); out; case CSR_BUS_TIME: oldcycle = host->csr.cycle_time; @@ -193,7 +166,8 @@ static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, /* cycle time wrapped around */ host->csr.bus_time += (1 << 7); } - *(buf++) = host->csr.bus_time | (host->csr.cycle_time >> 25); + *(buf++) = cpu_to_be32(host->csr.bus_time + | (host->csr.cycle_time >> 25)); out; /* address gap */ @@ -204,16 +178,16 @@ static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, return RCODE_ADDRESS_ERROR; case CSR_BUS_MANAGER_ID: - *(buf++) = host->csr.bus_manager_id; + *(buf++) = cpu_to_be32(host->csr.bus_manager_id); out; case CSR_BANDWIDTH_AVAILABLE: - *(buf++) = host->csr.bandwidth_available; + *(buf++) = cpu_to_be32(host->csr.bandwidth_available); out; case CSR_CHANNELS_AVAILABLE_HI: - *(buf++) = host->csr.channels_available_hi; + *(buf++) = cpu_to_be32(host->csr.channels_available_hi); out; case CSR_CHANNELS_AVAILABLE_LO: - *(buf++) = host->csr.channels_available_lo; + *(buf++) = cpu_to_be32(host->csr.channels_available_lo); out; /* address gap to end - fall through to default */ @@ -224,8 +198,8 @@ static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr, return RCODE_COMPLETE; } -static int write_regs(struct hpsb_host *host, quadlet_t *data, u64 addr, - unsigned int length) +static int write_regs(struct hpsb_host *host, int nodeid, quadlet_t *data, + u64 addr, unsigned int length) { int csraddr = addr - CSR_REGISTER_BASE; @@ -246,7 +220,7 @@ static int write_regs(struct hpsb_host *host, quadlet_t *data, u64 addr, case CSR_NODE_IDS: host->csr.node_ids &= NODE_MASK << 16; - host->csr.node_ids |= *(data++) & (BUS_MASK << 16); + host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16); host->node_id = host->csr.node_ids >> 16; host->template->devctl(host, SET_BUS_ID, host->node_id >> 6); out; @@ -259,10 +233,12 @@ static int write_regs(struct hpsb_host *host, quadlet_t *data, u64 addr, return RCODE_ADDRESS_ERROR; case CSR_SPLIT_TIMEOUT_HI: - host->csr.split_timeout_hi = *(data++) & 0x00000007; + host->csr.split_timeout_hi = + be32_to_cpu(*(data++)) & 0x00000007; out; case CSR_SPLIT_TIMEOUT_LO: - host->csr.split_timeout_lo = *(data++) & 0xfff80000; + host->csr.split_timeout_lo = + be32_to_cpu(*(data++)) & 0xfff80000; out; /* address gap */ @@ -270,11 +246,12 @@ static int write_regs(struct hpsb_host *host, quadlet_t *data, u64 addr, case CSR_CYCLE_TIME: /* should only be set by cycle start packet, automatically */ - host->csr.cycle_time = *data; - host->template->devctl(host, SET_CYCLE_COUNTER, *(data++)); + host->csr.cycle_time = be32_to_cpu(*data); + host->template->devctl(host, SET_CYCLE_COUNTER, + be32_to_cpu(*(data++))); out; case CSR_BUS_TIME: - host->csr.bus_time = *(data++) & 0xffffff80; + host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80; out; /* address gap */ @@ -305,13 +282,13 @@ static int write_regs(struct hpsb_host *host, quadlet_t *data, u64 addr, /* helper function for lock_regs */ inline static void compare_swap(quadlet_t *old, quadlet_t data, quadlet_t arg) { - if (*old == arg) { - *old = data; + if (*old == be32_to_cpu(arg)) { + *old = be32_to_cpu(data); } } -static int lock_regs(struct hpsb_host *host, quadlet_t *store, u64 addr, - quadlet_t data, quadlet_t arg, int extcode) +static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int extcode) { int csraddr = addr - CSR_REGISTER_BASE; unsigned long flags; @@ -327,25 +304,28 @@ static int lock_regs(struct hpsb_host *host, quadlet_t *store, u64 addr, switch (csraddr) { case CSR_BUS_MANAGER_ID: - *store = host->csr.bus_manager_id; + *store = cpu_to_be32(host->csr.bus_manager_id); compare_swap(&host->csr.bus_manager_id, data, arg); break; case CSR_BANDWIDTH_AVAILABLE: - *store = host->csr.bandwidth_available; + *store = cpu_to_be32(host-> + csr.bandwidth_available); compare_swap(&host->csr.bandwidth_available, data, arg); break; case CSR_CHANNELS_AVAILABLE_HI: - *store = host->csr.channels_available_hi; + *store = cpu_to_be32(host-> + csr.channels_available_hi); compare_swap(&host->csr.channels_available_hi, data, arg); break; case CSR_CHANNELS_AVAILABLE_LO: - *store = host->csr.channels_available_lo; + *store = cpu_to_be32(host-> + csr.channels_available_lo); compare_swap(&host->csr.channels_available_lo, data, arg); break; @@ -377,34 +357,48 @@ static int lock_regs(struct hpsb_host *host, quadlet_t *store, u64 addr, } } +static int write_fcp(struct hpsb_host *host, int nodeid, quadlet_t *data, + u64 addr, unsigned int length) +{ + int csraddr = addr - CSR_REGISTER_BASE; + + if (length > 512) { + return RCODE_TYPE_ERROR; + } + + switch (csraddr) { + case CSR_FCP_COMMAND: + highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length); + break; + case CSR_FCP_RESPONSE: + highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length); + break; + default: + return RCODE_TYPE_ERROR; + } + + return RCODE_COMPLETE; +} + struct hpsb_highlevel_ops csr_ops = { - add_host, - NULL, - host_reset, - NULL + add_host: add_host, + host_reset: host_reset, }; struct hpsb_address_ops map_ops = { - read_maps, - NULL, - NULL, - NULL + read: read_maps, }; struct hpsb_address_ops fcp_ops = { - read_fcp, - write_fcp, - NULL, - NULL + write: write_fcp, }; struct hpsb_address_ops reg_ops = { - read_regs, - write_regs, - lock_regs, - NULL + read: read_regs, + write: write_regs, + lock: lock_regs, }; diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h index 70bacdd10e0f..7bc97f549d66 100644 --- a/drivers/ieee1394/csr.h +++ b/drivers/ieee1394/csr.h @@ -46,7 +46,6 @@ struct csr_control { quadlet_t topology_map[256]; quadlet_t speed_map[1024]; - quadlet_t fcp_data[1024]; }; diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 3b4ac40f5475..3e20824aa99a 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -192,23 +192,35 @@ void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data, read_unlock(&hl_drivers_lock); } +void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, + u8 *data, unsigned int length) +{ + struct list_head *entry; + struct hpsb_highlevel *hl; + int cts = data[0]; + + read_lock(&hl_drivers_lock); + entry = hl_drivers.next; + + while (entry != &hl_drivers) { + hl = list_entry(entry, struct hpsb_highlevel, hl_list); + if (hl->op->fcp_request) { + hl->op->fcp_request(host, nodeid, direction, cts, data, + length); + } + entry = entry->next; + } + read_unlock(&hl_drivers_lock); +} -int highlevel_read(struct hpsb_host *host, quadlet_t *buffer, u64 addr, - unsigned int length) +int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, unsigned int length) { struct hpsb_address_serve *as; struct list_head *entry; unsigned int partlength; int rcode = RCODE_ADDRESS_ERROR; - if ((addr | length) & 0x3) { - /* Addresses or lengths not a multiple of a quadlet pose a big - * problem on little endian machines because we always do this - * in arch endian and swapping would mess it all up. So we - * simply don't allow this at all. */ - return RCODE_TYPE_ERROR; - } - read_lock(&addr_space_lock); entry = addr_space.next; @@ -220,7 +232,7 @@ int highlevel_read(struct hpsb_host *host, quadlet_t *buffer, u64 addr, length); if (as->op->read != NULL) { - rcode = as->op->read(host, buffer, addr, + rcode = as->op->read(host, nodeid, buffer, addr, partlength); } else { rcode = RCODE_TYPE_ERROR; @@ -247,18 +259,14 @@ int highlevel_read(struct hpsb_host *host, quadlet_t *buffer, u64 addr, return rcode; } -int highlevel_write(struct hpsb_host *host, quadlet_t *data, u64 addr, - unsigned int length) +int highlevel_write(struct hpsb_host *host, int nodeid, quadlet_t *data, + u64 addr, unsigned int length) { struct hpsb_address_serve *as; struct list_head *entry; unsigned int partlength; int rcode = RCODE_ADDRESS_ERROR; - if ((addr | length) & 0x3) { - return RCODE_TYPE_ERROR; - } - read_lock(&addr_space_lock); entry = addr_space.next; @@ -270,7 +278,7 @@ int highlevel_write(struct hpsb_host *host, quadlet_t *data, u64 addr, length); if (as->op->write != NULL) { - rcode = as->op->write(host, data, addr, + rcode = as->op->write(host, nodeid, data, addr, partlength); } else { rcode = RCODE_TYPE_ERROR; @@ -298,8 +306,8 @@ int highlevel_write(struct hpsb_host *host, quadlet_t *data, u64 addr, } -int highlevel_lock(struct hpsb_host *host, quadlet_t *store, u64 addr, - quadlet_t data, quadlet_t arg, int ext_tcode) +int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode) { struct hpsb_address_serve *as; struct list_head *entry; @@ -313,8 +321,8 @@ int highlevel_lock(struct hpsb_host *host, quadlet_t *store, u64 addr, while (as->start <= addr) { if (as->end > addr) { if (as->op->lock != NULL) { - rcode = as->op->lock(host, store, addr, data, - arg, ext_tcode); + rcode = as->op->lock(host, nodeid, store, addr, + data, arg, ext_tcode); } else { rcode = RCODE_TYPE_ERROR; } @@ -331,8 +339,8 @@ int highlevel_lock(struct hpsb_host *host, quadlet_t *store, u64 addr, return rcode; } -int highlevel_lock64(struct hpsb_host *host, octlet_t *store, u64 addr, - octlet_t data, octlet_t arg, int ext_tcode) +int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode) { struct hpsb_address_serve *as; struct list_head *entry; @@ -346,8 +354,9 @@ int highlevel_lock64(struct hpsb_host *host, octlet_t *store, u64 addr, while (as->start <= addr) { if (as->end > addr) { if (as->op->lock64 != NULL) { - rcode = as->op->lock64(host, store, addr, data, - arg, ext_tcode); + rcode = as->op->lock64(host, nodeid, store, + addr, data, arg, + ext_tcode); } else { rcode = RCODE_TYPE_ERROR; } diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h index 9bf40674295a..f4f615a7b2c0 100644 --- a/drivers/ieee1394/highlevel.h +++ b/drivers/ieee1394/highlevel.h @@ -55,6 +55,13 @@ struct hpsb_highlevel_ops { * for channel/host combinations you did not request. */ void (*iso_receive) (struct hpsb_host *host, int channel, quadlet_t *data, unsigned int length); + + /* A write request was received on either the FCP_COMMAND (direction = + * 0) or the FCP_RESPONSE (direction = 1) register. The cts arg + * contains the cts field (first byte of data). + */ + void (*fcp_request) (struct hpsb_host *host, int nodeid, int direction, + int cts, u8 *data, unsigned int length); }; struct hpsb_address_ops { @@ -67,17 +74,17 @@ struct hpsb_address_ops { */ /* These functions have to implement block reads for themselves. */ - int (*read) (struct hpsb_host *host, quadlet_t *buffer, u64 addr, - unsigned int length); - int (*write) (struct hpsb_host *host, quadlet_t *data, u64 addr, - unsigned int length); + int (*read) (struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, unsigned int length); + int (*write) (struct hpsb_host *host, int nodeid, quadlet_t *data, + u64 addr, unsigned int length); /* Lock transactions: write results of ext_tcode operation into * *store. */ - int (*lock) (struct hpsb_host *host, quadlet_t *store, u64 addr, - quadlet_t data, quadlet_t arg, int ext_tcode); - int (*lock64) (struct hpsb_host *host, octlet_t *store, u64 addr, - octlet_t data, octlet_t arg, int ext_tcode); + int (*lock) (struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode); + int (*lock64) (struct hpsb_host *host, int nodeid, octlet_t *store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode); }; @@ -87,17 +94,19 @@ void highlevel_add_host(struct hpsb_host *host); void highlevel_remove_host(struct hpsb_host *host); void highlevel_host_reset(struct hpsb_host *host); -int highlevel_read(struct hpsb_host *host, quadlet_t *buffer, u64 addr, - unsigned int length); -int highlevel_write(struct hpsb_host *host, quadlet_t *data, u64 addr, - unsigned int length); -int highlevel_lock(struct hpsb_host *host, quadlet_t *store, u64 addr, - quadlet_t data, quadlet_t arg, int ext_tcode); -int highlevel_lock64(struct hpsb_host *host, octlet_t *store, u64 addr, - octlet_t data, octlet_t arg, int ext_tcode); +int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, unsigned int length); +int highlevel_write(struct hpsb_host *host, int nodeid, quadlet_t *data, + u64 addr, unsigned int length); +int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode); +int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode); void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data, unsigned int length); +void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, + u8 *data, unsigned int length); /* diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h index dfca3aef303c..c9f42373e327 100644 --- a/drivers/ieee1394/ieee1394.h +++ b/drivers/ieee1394/ieee1394.h @@ -63,4 +63,103 @@ #define SELFID_PORT_NCONN 0x1 #define SELFID_PORT_NONE 0x0 + +#include + +#ifdef __BIG_ENDIAN_BITFIELD + +struct selfid { + u32 packet_identifier:2; /* always binary 10 */ + u32 phy_id:6; + /* byte */ + u32 extended:1; /* if true is struct ext_selfid */ + u32 link_active:1; + u32 gap_count:6; + /* byte */ + u32 speed:2; + u32 phy_delay:2; + u32 contender:1; + u32 power_class:3; + /* byte */ + u32 port0:2; + u32 port1:2; + u32 port2:2; + u32 initiated_reset:1; + u32 more_packets:1; +} __attribute__((packed)); + +struct ext_selfid { + u32 packet_identifier:2; /* always binary 10 */ + u32 phy_id:6; + /* byte */ + u32 extended:1; /* if false is struct selfid */ + u32 seq_nr:3; + u32 reserved:2; + u32 porta:2; + /* byte */ + u32 portb:2; + u32 portc:2; + u32 portd:2; + u32 porte:2; + /* byte */ + u32 portf:2; + u32 portg:2; + u32 porth:2; + u32 reserved2:1; + u32 more_packets:1; +} __attribute__((packed)); + +#elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */ + +/* + * Note: these mean to be bit fields of a big endian SelfID as seen on a little + * endian machine. + */ + +struct selfid { + u32 phy_id:6; + u32 packet_identifier:2; /* always binary 10 */ + /* byte */ + u32 gap_count:6; + u32 link_active:1; + u32 extended:1; /* if true is struct ext_selfid */ + /* byte */ + u32 power_class:3; + u32 contender:1; + u32 phy_delay:2; + u32 speed:2; + /* byte */ + u32 more_packets:1; + u32 initiated_reset:1; + u32 port2:2; + u32 port1:2; + u32 port0:2; +} __attribute__((packed)); + +struct ext_selfid { + u32 phy_id:6; + u32 packet_identifier:2; /* always binary 10 */ + /* byte */ + u32 porta:2; + u32 reserved:2; + u32 seq_nr:3; + u32 extended:1; /* if false is struct selfid */ + /* byte */ + u32 porte:2; + u32 portd:2; + u32 portc:2; + u32 portb:2; + /* byte */ + u32 more_packets:1; + u32 reserved2:1; + u32 porth:2; + u32 portg:2; + u32 portf:2; +} __attribute__((packed)); + +#else +#error What? PDP endian? +#endif /* __BIG_ENDIAN_BITFIELD */ + + #endif /* _IEEE1394_IEEE1394_H */ diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 771189f0b37e..c7ce7314437a 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -2,11 +2,12 @@ * IEEE 1394 for Linux * * Core support: hpsb_packet management, packet handling and forwarding to - * csr or lowlevel code + * highlevel or lowlevel code * * Copyright (C) 1999, 2000 Andreas E. Bombe */ +#include #include #include #include @@ -62,7 +63,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size) packet->header = header; if (data_size) { - data = kmalloc(data_size + 4, kmflags); + data = kmalloc(data_size + 8, kmflags); if (data == NULL) { kfree(header); kfree(packet); @@ -70,18 +71,14 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size) } packet->data = data; - packet->data_size = data_size - 4; + packet->data_size = data_size; } INIT_LIST_HEAD(&packet->list); sema_init(&packet->state_change, 0); packet->state = unused; packet->generation = get_hpsb_generation(); - -#ifdef __BIG_ENDIAN - /* set default */ packet->data_be = 1; -#endif return packet; } @@ -133,59 +130,55 @@ static int check_selfids(struct hpsb_host *host, unsigned int num_of_selfids) { int nodeid = -1; int rest_of_selfids = num_of_selfids; - quadlet_t *sidp = host->topology_map; - quadlet_t sid = *sidp; + struct selfid *sid = (struct selfid *)host->topology_map; + struct ext_selfid *esid; int esid_seq = 23; - int i; while (rest_of_selfids--) { - sid = *(sidp++); - - if (!(sid & 0x00800000) /* !extended */) { + if (!sid->extended) { nodeid++; esid_seq = 0; - - if (((sid >> 24) & NODE_MASK) != nodeid) { + + if (sid->phy_id != nodeid) { HPSB_INFO("SelfIDs failed monotony check with " - "%d", (sid >> 24) & NODE_MASK); + "%d", sid->phy_id); return 0; } - - /* "if is contender and link active" */ - if ((sid & (1<<11)) && (sid & (1<<22))) { - host->irm_id = LOCAL_BUS | ((sid >> 24) - & NODE_MASK); + + if (sid->contender && sid->link_active) { + host->irm_id = LOCAL_BUS | sid->phy_id; } } else { - if ((((sid >> 24) & NODE_MASK) != nodeid) - || (((sid >> 20) & 0x7) != esid_seq)) { + esid = (struct ext_selfid *)sid; + + if ((esid->phy_id != nodeid) + || (esid->seq_nr != esid_seq)) { HPSB_INFO("SelfIDs failed monotony check with " - "%d/%d", (sid >> 24) & NODE_MASK, - (sid >> 20) & 0x7); + "%d/%d", esid->phy_id, esid->seq_nr); return 0; } esid_seq++; } - } - - sidp--; - while (sid & 0x00800000 /* extended */) { - /* check that no ports go to a parent */ - for (i = 2; i < 18; i += 2) { - if ((sid & (0x3 << i)) == (0x2 << i)) { + sid++; + } + + esid = (struct ext_selfid *)(sid - 1); + while (esid->extended) { + if ((esid->porta == 0x2) || (esid->portb == 0x2) + || (esid->portc == 0x2) || (esid->portd == 0x2) + || (esid->porte == 0x2) || (esid->portf == 0x2) + || (esid->portg == 0x2) || (esid->porth == 0x2)) { HPSB_INFO("SelfIDs failed root check on " "extended SelfID"); return 0; - } } - sid = *(sidp--); + esid--; } - for (i = 2; i < 8; i += 2) { - if ((sid & (0x3 << i)) == (0x2 << i)) { + sid = (struct selfid *)esid; + if ((sid->port0 == 0x2) || (sid->port1 == 0x2) || (sid->port2 == 0x2)) { HPSB_INFO("SelfIDs failed root check"); return 0; - } } return nodeid + 1; @@ -196,7 +189,8 @@ static void build_speed_map(struct hpsb_host *host, int nodecount) char speedcap[nodecount]; char cldcnt[nodecount]; u8 *map = host->speed_map; - quadlet_t *sidp; + struct selfid *sid; + struct ext_selfid *esid; int i, j, n; for (i = 0; i < (nodecount * 64); i += 64) { @@ -210,22 +204,26 @@ static void build_speed_map(struct hpsb_host *host, int nodecount) } /* find direct children count and speed */ - for (sidp = &host->topology_map[host->selfid_count-1], + for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1], n = nodecount - 1; - sidp >= host->topology_map; sidp--) { - if (*sidp & 0x00800000 /* extended */) { - for (i = 2; i < 18; i += 2) { - if ((*sidp & (0x3 << i)) == (0x3 << i)) { - cldcnt[n]++; - } - } + (void *)sid >= (void *)host->topology_map; sid--) { + if (sid->extended) { + esid = (struct ext_selfid *)sid; + + if (esid->porta == 0x3) cldcnt[n]++; + if (esid->portb == 0x3) cldcnt[n]++; + if (esid->portc == 0x3) cldcnt[n]++; + if (esid->portd == 0x3) cldcnt[n]++; + if (esid->porte == 0x3) cldcnt[n]++; + if (esid->portf == 0x3) cldcnt[n]++; + if (esid->portg == 0x3) cldcnt[n]++; + if (esid->porth == 0x3) cldcnt[n]++; } else { - for (i = 2; i < 8; i += 2) { - if ((*sidp & (0x3 << i)) == (0x3 << i)) { - cldcnt[n]++; - } - } - speedcap[n] = (*sidp >> 14) & 0x3; + if (sid->port0 == 0x3) cldcnt[n]++; + if (sid->port1 == 0x3) cldcnt[n]++; + if (sid->port2 == 0x3) cldcnt[n]++; + + speedcap[n] = sid->speed; n--; } } @@ -262,7 +260,7 @@ static void build_speed_map(struct hpsb_host *host, int nodecount) void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid) { if (host->in_bus_reset) { - printk("including selfid 0x%x\n", sid); + HPSB_DEBUG("including selfid 0x%x", sid); host->topology_map[host->selfid_count++] = sid; } else { /* FIXME - info on which host */ @@ -293,7 +291,12 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) } /* irm_id is kept up to date by check_selfids() */ - host->is_irm = (host->irm_id == host->node_id); + if (host->irm_id == host->node_id) { + host->is_irm = 1; + host->is_busmgr = 1; + host->busmgr_id = host->node_id; + host->csr.bus_manager_id = host->node_id; + } host->reset_retries = 0; inc_hpsb_generation(); @@ -346,6 +349,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) packet->speed_code = host->speed_map[(host->node_id & NODE_MASK) * 64 + (packet->node_id & NODE_MASK)]; +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG switch (packet->speed_code) { case 2: dump_packet("send packet 400:", packet->header, @@ -359,6 +363,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) dump_packet("send packet 100:", packet->header, packet->header_size); } +#endif return host->template->transmit_packet(host, packet); } @@ -459,12 +464,14 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data, { struct hpsb_packet *p; + dsize += (dsize % 4 ? 4 - (dsize % 4) : 0); + p = alloc_hpsb_packet(dsize); if (p == NULL) { /* FIXME - send data_error response */ return NULL; } - + p->type = async; p->state = unused; p->host = host; @@ -472,6 +479,10 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data, p->tlabel = (data[0] >> 10) & 0x3f; p->no_waiter = 1; + if (dsize % 4) { + p->data[dsize / 4] = 0; + } + return p; } @@ -479,21 +490,12 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data, packet = create_reply_packet(host, data, length); \ if (packet == NULL) break -inline void swap_quadlets_on_le(quadlet_t *q) -{ -#ifdef __LITTLE_ENDIAN - quadlet_t saved = q[0]; - q[0] = q[1]; - q[1] = saved; -#endif -} - - void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, size_t size) { struct hpsb_packet *packet; int length, rcode, extcode; + int source = data[1] >> 16; u64 addr; /* big FIXME - no error checking is done for an out of bounds length */ @@ -501,7 +503,7 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, switch (tcode) { case TCODE_WRITEQ: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_write(host, data+3, addr, 4); + rcode = highlevel_write(host, source, data+3, addr, 4); if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) { /* not a broadcast write, reply */ @@ -513,7 +515,8 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, case TCODE_WRITEB: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_write(host, data+4, addr, data[3]>>16); + rcode = highlevel_write(host, source, data+4, addr, + data[3]>>16); if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) { /* not a broadcast write, reply */ @@ -527,7 +530,7 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, PREP_REPLY_PACKET(0); addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_read(host, data, addr, 4); + rcode = highlevel_read(host, source, data, addr, 4); fill_async_readquad_resp(packet, rcode, *data); send_packet_nocare(packet); break; @@ -537,7 +540,8 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, PREP_REPLY_PACKET(length); addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_read(host, packet->data, addr, length); + rcode = highlevel_read(host, source, packet->data, addr, + length); fill_async_readblock_resp(packet, rcode, length); send_packet_nocare(packet); break; @@ -556,35 +560,32 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, switch (length) { case 4: - rcode = highlevel_lock(host, packet->data, addr, + rcode = highlevel_lock(host, source, packet->data, addr, data[4], 0, extcode); fill_async_lock_resp(packet, rcode, extcode, 4); break; case 8: if ((extcode != EXTCODE_FETCH_ADD) && (extcode != EXTCODE_LITTLE_ADD)) { - rcode = highlevel_lock(host, packet->data, addr, + rcode = highlevel_lock(host, source, + packet->data, addr, data[5], data[4], extcode); fill_async_lock_resp(packet, rcode, extcode, 4); } else { - swap_quadlets_on_le(data + 4); - rcode = highlevel_lock64(host, + rcode = highlevel_lock64(host, source, (octlet_t *)packet->data, addr, *(octlet_t *)(data + 4), 0ULL, extcode); - swap_quadlets_on_le(packet->data); fill_async_lock_resp(packet, rcode, extcode, 8); } break; case 16: - swap_quadlets_on_le(data + 4); - swap_quadlets_on_le(data + 6); - rcode = highlevel_lock64(host, (octlet_t *)packet->data, - addr, *(octlet_t *)(data + 6), + rcode = highlevel_lock64(host, source, + (octlet_t *)packet->data, addr, + *(octlet_t *)(data + 6), *(octlet_t *)(data + 4), extcode); - swap_quadlets_on_le(packet->data); fill_async_lock_resp(packet, rcode, extcode, 8); break; default: @@ -609,7 +610,9 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size) return; } +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG dump_packet("received packet:", data, size); +#endif tcode = (data[0] >> 4) & 0xf; diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 171a2fa9fe84..636aef40e958 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -40,29 +40,26 @@ struct hpsb_packet { unsigned no_waiter:1; /* Data big endianness flag - may vary from request to request. The - * header is always in machine byte order. */ + * header is always in machine byte order. + * Not really used currently. */ unsigned data_be:1; /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */ unsigned speed_code:2; - /* --- 16 bytes (one cacheline) --- */ - - /* *header and *data are guaranteed to be 32-bit DMAable and may be + /* + * *header and *data are guaranteed to be 32-bit DMAable and may be * overwritten to allow in-place byte swapping. Neither of these is * CRCed (the sizes also don't include CRC), but contain space for at * least one additional quadlet to allow in-place CRCing. The memory is * also guaranteed to have physical mapping (virt_to_bus() is meaningful * on these pointers). - * NOTE: The 32-bit DMA guarantee is currently not enforced. - * That's a Linux 2.3 issue. */ quadlet_t *header; quadlet_t *data; size_t header_size; size_t data_size; - /* --- 32 bytes --- */ struct hpsb_host *host; unsigned int generation; @@ -139,12 +136,14 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot); * for other cases (internal errors that don't justify a panic). Safe to call * from within a transmit packet routine. */ -void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, int ackcode); +void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, + int ackcode); /* * Hand over received packet to the core. The contents of data are expected to * be the full packet but with the CRCs left out (data block follows header - * immediately) and in machine byte order. *data can be safely overwritten + * immediately), with the header (i.e. the first four quadlets) in machine byte + * order and the data block in big endian. *data can be safely overwritten * after this call. */ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size); diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index e2eeffc682da..6f07a7f6a2e9 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -68,7 +68,7 @@ void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE); packet->header[3] = length << 16; packet->header_size = 16; - packet->data_size = length; + packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); } void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data) @@ -85,8 +85,8 @@ void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length) PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB); packet->header[3] = length << 16; packet->header_size = 16; - packet->data_size = length; packet->expect_response = 1; + packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); } void fill_async_write_resp(struct hpsb_packet *packet, int rcode) @@ -260,7 +260,7 @@ int hpsb_read_trylocal(struct hpsb_host *host, nodeid_t node, u64 addr, quadlet_t *buffer, size_t length) { if (host->node_id != node) return -1; - return highlevel_read(host, buffer, addr, length); + return highlevel_read(host, node, buffer, addr, length); } struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node, @@ -284,7 +284,7 @@ struct hpsb_packet *hpsb_make_readbpacket(struct hpsb_host *host, nodeid_t node, { struct hpsb_packet *p; - p = alloc_hpsb_packet(length); + p = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); if (!p) return NULL; p->host = host; @@ -318,9 +318,13 @@ struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host, { struct hpsb_packet *p; - p = alloc_hpsb_packet(length); + p = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); if (!p) return NULL; + if (length % 4) { + p->data[length / 4] = 0; + } + p->host = host; p->tlabel = get_tlabel(host, node, 1); p->node_id = node; @@ -370,7 +374,7 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr, } if (host->node_id == node) { - switch(highlevel_read(host, buffer, addr, length)) { + switch(highlevel_read(host, node, buffer, addr, length)) { case RCODE_COMPLETE: return 0; case RCODE_TYPE_ERROR: @@ -381,16 +385,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr, } } - if (length & 0x3) { - /* FIXME: Lengths not multiple of 4 are not implemented. Mainly - * there is the problem with little endian machines because we - * always swap to little endian on receive. If we read 5 bytes - * 12345 we receive them as 12345000 and swap them to 43210005. - * How should we copy that to the caller? Require *buffer to be - * a full quadlet multiple in length? */ - return -EACCES; - } - if (length == 4) { packet = hpsb_make_readqpacket(host, node, addr); } else { @@ -432,7 +426,7 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr, } if (host->node_id == node) { - switch(highlevel_write(host, buffer, addr, length)) { + switch(highlevel_write(host, node, buffer, addr, length)) { case RCODE_COMPLETE: return 0; case RCODE_TYPE_ERROR: @@ -443,12 +437,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr, } } - if (length & 0x3) { - /* FIXME: Lengths not multiple of 4 are not implemented. See function - * hpsb_read for explanation, same reason, different direction. */ - return -EACCES; - } - if (length == 4) { packet = hpsb_make_writeqpacket(host, node, addr, *buffer); } else { @@ -483,7 +471,8 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, u64 addr, int extcode, int retval = 0, length; if (host->node_id == node) { - switch(highlevel_lock(host, data, addr, *data, arg, extcode)) { + switch(highlevel_lock(host, node, data, addr, *data, arg, + extcode)) { case RCODE_COMPLETE: return 0; case RCODE_TYPE_ERROR: diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index d619182dd87b..d817e61c6a95 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -6,6 +6,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) @@ -24,6 +25,8 @@ static __inline__ void list_add_tail(struct list_head *new, struct list_head *he __list_add(new, head->prev, head); } +#define __constant_cpu_to_be32(x) __constant_htonl((x)) + #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index b8fae7ee274e..488e013fbb5c 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -35,9 +35,18 @@ * . Config ROM * * Known bugs: - * . Self-id are not received properly if card - * is initialized with no other nodes on the - * bus. + * . Self-id are sometimes not received properly + * if card is initialized with no other nodes + * on the bus + */ + +/* + * Acknowledgments: + * + * Emilie Chung + * .Tip on Async Request Filter + * Pascal Drolet + * .Various tips for optimization and functionnalities */ #include @@ -71,11 +80,15 @@ #include "ieee1394_core.h" #include "ohci1394.h" +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG +#define OHCI1394_DEBUG +#endif + #ifdef DBGMSG #undef DBGMSG #endif -#if OHCI1394_DEBUG +#ifdef OHCI1394_DEBUG #define DBGMSG(card, fmt, args...) \ printk(KERN_INFO "ohci1394_%d: " fmt "\n" , card , ## args) #else @@ -97,10 +110,14 @@ printk(level "ohci1394_%d: " fmt "\n" , card , ## args) return 1; int supported_chips[][2] = { - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394 }, - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_2 }, + { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_LV22 }, + { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_LV23 }, + { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_LV26 }, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_OHCI1394 }, { PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_SONY_CXD3222 }, + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72862 }, + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72870 }, + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72871 }, { -1, -1 } }; @@ -213,7 +230,7 @@ inline static int handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host, if (q[0] == ~q[1]) { PRINT(KERN_INFO, ohci->id, "selfid packet 0x%x rcvd", q[0]); - hpsb_selfid_received(host, q[0]); + hpsb_selfid_received(host, cpu_to_be32(q[0])); if (((q[0]&0x3f000000)>>24)==phyid) { lsid=q[0]; PRINT(KERN_INFO, ohci->id, @@ -369,6 +386,23 @@ static void initialize_dma_trm_ctx(struct dma_trm_ctx *d) PRINT(KERN_INFO, ohci->id, "AT dma ctx=%d initialized", d->ctx); } +/* Count the number of available iso contexts */ +static int get_nb_iso_ctx(struct ti_ohci *ohci) +{ + int i,ctx=0; + u32 tmp; + + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0xffffffff); + tmp = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); + + /* Count the number of contexts */ + for(i=0; i<32; i++) { + if(tmp & 1) ctx++; + tmp >>= 1; + } + return ctx; +} + /* Global initialization */ static int ohci_initialize(struct hpsb_host *host) { @@ -411,15 +445,22 @@ static int ohci_initialize(struct hpsb_host *host) virt_to_bus(ohci->csr_config_rom)); /* Write the config ROM header */ - reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->csr_config_rom[0]); + reg_write(ohci, OHCI1394_ConfigROMhdr, + cpu_to_be32(ohci->csr_config_rom[0])); /* Set bus options */ - reg_write(ohci, OHCI1394_BusOptions, ohci->csr_config_rom[2]); - - /* Write the GUID into the csr config rom */ - ohci->csr_config_rom[3] = reg_read(ohci, OHCI1394_GUIDHi); - ohci->csr_config_rom[4] = reg_read(ohci, OHCI1394_GUIDLo); + reg_write(ohci, OHCI1394_BusOptions, + cpu_to_be32(ohci->csr_config_rom[2])); + /* Write the GUID into the csr config rom */ + ohci->csr_config_rom[3] = be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi)); + ohci->csr_config_rom[4] = be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo)); + + ohci->max_packet_size = + 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); + PRINT(KERN_INFO, ohci->id, "max packet size = %d bytes", + ohci->max_packet_size); + /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); @@ -427,7 +468,10 @@ static int ohci_initialize(struct hpsb_host *host) reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); /* Initialize IR dma */ - for (i=0;i<4;i++) { /* FIXME : how many contexts are available ? */ + ohci->nb_iso_ctx = get_nb_iso_ctx(ohci); + PRINT(KERN_INFO, ohci->id, "%d iso contexts available", + ohci->nb_iso_ctx); + for (i=0;inb_iso_ctx;i++) { reg_write(ohci, OHCI1394_IrRcvContextControlClear+32*i, 0xffffffff); reg_write(ohci, OHCI1394_IrRcvContextMatch+32*i, 0); @@ -465,7 +509,6 @@ static int ohci_initialize(struct hpsb_host *host) * Accept AT requests from all nodes. This probably * will have to be controlled from the subsystem * on a per node basis. - * (Tip by Emilie Chung ) */ reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000); @@ -578,8 +621,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) unsigned char tcode; int i=50; - if (packet->data_size >= 4096) { - PRINT(KERN_ERR, ohci->id, "transmit packet data too big (%d)", + if (packet->data_size >= ohci->max_packet_size) { + PRINT(KERN_ERR, ohci->id, + "transmit packet size = %d too big", packet->data_size); return 0; } @@ -587,24 +631,8 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) /* Decide wether we have a request or a response packet */ tcode = (packet->header[0]>>4)&0xf; - if ((tcode==TCODE_READQ)|| - (tcode==TCODE_WRITEQ)|| - (tcode==TCODE_READB)|| - (tcode==TCODE_WRITEB)|| - (tcode==TCODE_LOCK_REQUEST)) - d = ohci->at_req_context; - - else if ((tcode==TCODE_WRITE_RESPONSE)|| - (tcode==TCODE_READQ_RESPONSE)|| - (tcode==TCODE_READB_RESPONSE)|| - (tcode==TCODE_LOCK_RESPONSE)) - d = ohci->at_resp_context; - - else { - PRINT(KERN_ERR, ohci->id, - "Unexpected packet tcode=%d in AT DMA", tcode); - return 0; - } + if (tcode & 0x02) d = ohci->at_resp_context; + else d = ohci->at_req_context; spin_lock(&d->lock); @@ -659,6 +687,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) switch (cmd) { case RESET_BUS: + host->attempt_root=1; PRINT(KERN_INFO, ohci->id, "resetting bus on request%s", (host->attempt_root ? " and attempting to become root" : "")); @@ -679,15 +708,21 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) break; case ACT_CYCLE_MASTER: -#if 0 if (arg) { - /* enable cycleTimer, cycleMaster, cycleSource */ - reg_write(ohci, OHCI1394_LinkControlSet, 0x00700000); + /* check if we are root and other nodes are present */ + u32 nodeId = reg_read(ohci, OHCI1394_NodeID); + if ((nodeId & (1<<30)) && (nodeId & 0x3f)) { + /* + * enable cycleTimer cycleMaster cycleSource + */ + DBGMSG(ohci->id, "Cycle master enabled"); + reg_write(ohci, OHCI1394_LinkControlSet, + 0x00700000); + } } else { /* disable cycleTimer, cycleMaster, cycleSource */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00700000); - }; -#endif + } break; case CANCEL_REQUESTS: @@ -811,8 +846,20 @@ static void ohci_irq_handler(int irq, void *dev_id, struct hpsb_host *host = ohci->host; int phyid = -1, isroot = 0; + /* read the interrupt event register */ event=reg_read(ohci, OHCI1394_IntEventSet); +#if 0 + /* + * clear the interrupt event register, except for the + * bus reset event interrupt (if any). This is an + * attempt to comply with ohci spec 7.2.3.2 + */ + reg_write(ohci, OHCI1394_IntEventClear, event & (~OHCI1394_busReset)); +#else + /* The above attempt doesn't work */ + reg_write(ohci, OHCI1394_IntEventClear, event); +#endif if (event & OHCI1394_busReset) { if (!host->in_bus_reset) { PRINT(KERN_INFO, ohci->id, "Bus reset"); @@ -821,6 +868,11 @@ static void ohci_irq_handler(int irq, void *dev_id, dma_trm_reset(ohci->at_req_context); dma_trm_reset(ohci->at_resp_context); +#if 0 + /* clear the bus reset event */ + reg_write(ohci, OHCI1394_IntEventClear, + OHCI1394_busReset); +#endif /* Subsystem call */ hpsb_bus_reset(ohci->host); @@ -891,7 +943,7 @@ static void ohci_irq_handler(int irq, void *dev_id, if (event & OHCI1394_selfIDComplete) { if (host->in_bus_reset) { node_id = reg_read(ohci, OHCI1394_NodeID); - if (node_id & 0x8000000) { /* NodeID valid */ + if (node_id & 0x80000000) { /* NodeID valid */ phyid = node_id & 0x0000003f; isroot = (node_id & 0x40000000) != 0; @@ -924,8 +976,6 @@ static void ohci_irq_handler(int irq, void *dev_id, #endif } - /* clear the interrupt event register */ - reg_write(ohci, OHCI1394_IntEventClear, event); } /* Put the buffer back into the dma context */ @@ -963,44 +1013,34 @@ static int block_length(struct dma_rcv_ctx *d, int idx, return length; } -static int packet_length(struct dma_rcv_ctx *d, int idx, - quadlet_t *buf_ptr, int offset) +const int TCODE_SIZE[16] = {20, 0, 16, -1, 16, 20, 20, 0, + -1, 0, -1, 0, -1, -1, 16, -1}; + +/* + * Determine the length of a packet in the buffer + * Optimization suggested by Pascal Drolet + */ +static int packet_length(struct dma_rcv_ctx *d, int idx, quadlet_t *buf_ptr, +int offset) { - unsigned char tcode; - int length; + unsigned char tcode; + int length = -1; /* Let's see what kind of packet is in there */ - tcode = (buf_ptr[0]>>4)&0xf; - - if (d->ctx==0) { /* Async Receive Request */ - if (tcode==TCODE_READQ) return 16; - else if (tcode==TCODE_WRITEQ || - tcode==TCODE_READB) return 20; - else if (tcode==TCODE_WRITEB || - tcode==TCODE_LOCK_REQUEST) { - return block_length(d, idx, buf_ptr, offset) + 20; - } - else if (tcode==0xE) { /* Phy packet */ - return 16; - } - else return -1; - } - else if (d->ctx==1) { /* Async Receive Response */ - if (tcode==TCODE_WRITE_RESPONSE) return 16; - else if (tcode==TCODE_READQ_RESPONSE) return 20; - else if (tcode==TCODE_READB_RESPONSE || - tcode==TCODE_LOCK_RESPONSE) { - return block_length(d, idx, buf_ptr, offset) + 20; - } - else return -1; + tcode = (buf_ptr[0] >> 4) & 0xf; + + if (d->ctx < 2) { /* Async Receive Response/Request */ + length = TCODE_SIZE[tcode]; + if (length == 0) + length = block_length(d, idx, buf_ptr, offset) + 20; } else if (d->ctx==2) { /* Iso receive */ /* Assumption: buffer fill mode with header/trailer */ length = (buf_ptr[0]>>16); if (length % 4) length += 4 - (length % 4); - return length+8; + length+=8; } - return -1; + return length; } /* Bottom half that processes dma receive buffers */ @@ -1336,6 +1376,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, int ctx, int num_desc, static int add_card(struct pci_dev *dev) { struct ti_ohci *ohci; /* shortcut to currently handled device */ + int i; if (num_of_cards == MAX_OHCI1394_CARDS) { PRINT_G(KERN_WARNING, "cannot handle more than %d cards. " @@ -1344,6 +1385,10 @@ static int add_card(struct pci_dev *dev) return 1; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + pci_enable_device(dev); +#endif + ohci = &cards[num_of_cards++]; ohci->id = num_of_cards-1; @@ -1363,7 +1408,11 @@ static int add_card(struct pci_dev *dev) if (ohci->csr_config_rom == NULL) { FAIL("failed to allocate buffer config rom"); } - memcpy(ohci->csr_config_rom, ohci_csr_rom, sizeof(ohci_csr_rom)); + for (i=0;icsr_config_rom[i] = cpu_to_be32(ohci_csr_rom[i]); + + DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x", + *((char *)ohci->csr_config_rom+4)); /* self-id dma buffer allocation */ ohci->self_id_buffer = kmalloc(2048, GFP_KERNEL); diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h index 46d9a270fd2d..f0ec83d48021 100644 --- a/drivers/ieee1394/ohci1394.h +++ b/drivers/ieee1394/ohci1394.h @@ -4,16 +4,18 @@ #include "ieee1394_types.h" -#define OHCI1394_DEBUG 1 - #define OHCI1394_DRIVER_NAME "ohci1394" -#ifndef PCI_DEVICE_ID_TI_OHCI1394 -#define PCI_DEVICE_ID_TI_OHCI1394 0x8009 -#endif +#ifndef PCI_DEVICE_ID_TI_OHCI1394_LV22 +#define PCI_DEVICE_ID_TI_OHCI1394_LV22 0x8009 +#endif + +#ifndef PCI_DEVICE_ID_TI_OHCI1394_LV23 +#define PCI_DEVICE_ID_TI_OHCI1394_LV23 0x8019 +#endif -#ifndef PCI_DEVICE_ID_TI_OHCI1394_2 -#define PCI_DEVICE_ID_TI_OHCI1394_2 0x8019 +#ifndef PCI_DEVICE_ID_TI_OHCI1394_LV26 +#define PCI_DEVICE_ID_TI_OHCI1394_LV26 0x8020 #endif #ifndef PCI_DEVICE_ID_VIA_OHCI1394 @@ -28,6 +30,22 @@ #define PCI_DEVICE_ID_SONY_CXD3222 0x8039 #endif +#ifndef PCI_DEVICE_ID_NEC_1394 +#define PCI_DEVICE_ID_NEC_1394 0x00cd +#endif + +#ifndef PCI_DEVICE_ID_NEC_UPD72862 +#define PCI_DEVICE_ID_NEC_UPD72862 0x0063 +#endif + +#ifndef PCI_DEVICE_ID_NEC_UPD72870 +#define PCI_DEVICE_ID_NEC_UPD72870 0x00cd +#endif + +#ifndef PCI_DEVICE_ID_NEC_UPD72871 +#define PCI_DEVICE_ID_NEC_UPD72871 0x00ce +#endif + #define MAX_OHCI1394_CARDS 4 #define OHCI1394_MAX_AT_REQ_RETRIES 0x2 @@ -113,6 +131,8 @@ struct ti_ohci { quadlet_t *self_id_buffer; /* dma buffer for self-id packets */ quadlet_t *csr_config_rom; /* buffer for csr config rom */ + unsigned int max_packet_size; + /* async receive */ struct dma_rcv_ctx *ar_resp_context; struct dma_rcv_ctx *ar_req_context; @@ -125,6 +145,7 @@ struct ti_ohci { struct dma_rcv_ctx *ir_context; u64 IR_channel_usage; spinlock_t IR_channel_lock; + int nb_iso_ctx; /* IEEE-1394 part follows */ struct hpsb_host *host; diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 2714a6eb5aca..773d68983431 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -59,6 +59,13 @@ /* print card specific information */ #define PRINT(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args) +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG +#define PRINT_GD(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args) +#define PRINTD(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args) +#else +#define PRINT_GD(level, fmt, args...) +#define PRINTD(level, card, fmt, args...) +#endif static struct ti_lynx cards[MAX_PCILYNX_CARDS]; static int num_of_cards = 0; @@ -313,7 +320,8 @@ static quadlet_t generate_own_selfid(struct ti_lynx *lynx, } } - printk("-%d- generated own selfid 0x%x\n", lynx->id, lsid); + cpu_to_be32s(&lsid); + PRINT(KERN_DEBUG, lynx->id, "generated own selfid 0x%x", lsid); return lsid; } @@ -322,7 +330,14 @@ static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host, size_t s quadlet_t *q = lynx->rcv_page; int phyid, isroot; quadlet_t lsid = 0; + int i; + i = (size > 16 ? 16 : size) / 4 - 1; + while (i >= 0) { + cpu_to_be32s(&q[i]); + i--; + } + if (!lynx->phyic.reg_1394a) { lsid = generate_own_selfid(lynx, host); } @@ -339,17 +354,20 @@ static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host, size_t s } while (size > 0) { - if (!lynx->phyic.reg_1394a - && (q[0] & 0x3f800000) == ((phyid + 1) << 24)) { + struct selfid *sid = (struct selfid *)q; + + if (!lynx->phyic.reg_1394a && !sid->extended + && (sid->phy_id == (phyid + 1))) { hpsb_selfid_received(host, lsid); } if (q[0] == ~q[1]) { - printk("-%d- selfid packet 0x%x rcvd\n", lynx->id, q[0]); + PRINT(KERN_DEBUG, lynx->id, "selfid packet 0x%x rcvd", + q[0]); hpsb_selfid_received(host, q[0]); } else { - printk("-%d- inconsistent selfid 0x%x/0x%x\n", lynx->id, - q[0], q[1]); + PRINT(KERN_INFO, lynx->id, + "inconsistent selfid 0x%x/0x%x", q[0], q[1]); } q += 2; size -= 8; @@ -429,14 +447,14 @@ static int lynx_initialize(struct hpsb_host *host) pcl.next = PCL_NEXT_INVALID; pcl.async_error_next = PCL_NEXT_INVALID; #ifdef __BIG_ENDIAN - pcl.buffer[0].control = PCL_CMD_RCV | 2048; - pcl.buffer[1].control = PCL_LAST_BUFF | 2048; + pcl.buffer[0].control = PCL_CMD_RCV | 16; + pcl.buffer[1].control = PCL_LAST_BUFF | 4080; #else - pcl.buffer[0].control = PCL_CMD_RCV | PCL_BIGENDIAN | 2048; - pcl.buffer[1].control = PCL_LAST_BUFF | PCL_BIGENDIAN | 2048; + pcl.buffer[0].control = PCL_CMD_RCV | PCL_BIGENDIAN | 16; + pcl.buffer[1].control = PCL_LAST_BUFF | 4080; #endif pcl.buffer[0].pointer = virt_to_bus(lynx->rcv_page); - pcl.buffer[1].pointer = virt_to_bus(lynx->rcv_page) + 2048; + pcl.buffer[1].pointer = virt_to_bus(lynx->rcv_page) + 16; put_pcl(lynx, lynx->rcv_pcl, &pcl); pcl.next = pcl_bus(lynx, lynx->async_pcl); @@ -445,10 +463,11 @@ static int lynx_initialize(struct hpsb_host *host) pcl.next = PCL_NEXT_INVALID; pcl.async_error_next = PCL_NEXT_INVALID; - pcl.buffer[0].control = PCL_CMD_RCV | PCL_LAST_BUFF | 2048; + pcl.buffer[0].control = PCL_CMD_RCV | 4; #ifndef __BIG_ENDIAN pcl.buffer[0].control |= PCL_BIGENDIAN; #endif + pcl.buffer[1].control = PCL_LAST_BUFF | 2044; for (i = 0; i < NUM_ISORCV_PCL; i++) { int page = i / ISORCV_PER_PAGE; @@ -456,6 +475,7 @@ static int lynx_initialize(struct hpsb_host *host) pcl.buffer[0].pointer = virt_to_bus(lynx->iso_rcv.page[page]) + sec * MAX_ISORCV_SIZE; + pcl.buffer[1].pointer = pcl.buffer[0].pointer + 4; put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl); } @@ -539,6 +559,10 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet) } packet->xnext = NULL; + if (packet->tcode == TCODE_WRITEQ + || packet->tcode == TCODE_READQ_RESPONSE) { + cpu_to_be32s(&packet->header[3]); + } spin_lock_irqsave(&lynx->async_queue_lock, flags); @@ -1054,8 +1078,8 @@ static void lynx_irq_handler(int irq, void *dev_id, } if (linkint & LINK_INT_PHY_REG_RCVD) { if (!host->in_bus_reset) { - printk("-%d- phy reg received without reset\n", - lynx->id); + PRINT(KERN_INFO, lynx->id, + "phy reg received without reset"); } } if (linkint & LINK_INT_ISO_STUCK) { @@ -1082,7 +1106,7 @@ static void lynx_irq_handler(int irq, void *dev_id, } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_RCV)) { - PRINT(KERN_INFO, lynx->id, "iso receive"); + PRINTD(KERN_DEBUG, lynx->id, "iso receive"); spin_lock(&lynx->iso_rcv.lock); @@ -1094,7 +1118,7 @@ static void lynx_irq_handler(int irq, void *dev_id, if ((lynx->iso_rcv.next == lynx->iso_rcv.last) || !lynx->iso_rcv.chan_count) { - printk("stopped\n"); + PRINTD(KERN_DEBUG, lynx->id, "stopped"); reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0); } @@ -1125,9 +1149,9 @@ static void lynx_irq_handler(int irq, void *dev_id, spin_unlock(&lynx->async_queue_lock); if (ack & DMA_CHAN_STAT_SPECIALACK) { - printk("-%d- special ack %d\n", lynx->id, - (ack >> 15) & 0xf); - ack = ACKX_SEND_ERROR; + ack = (ack >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); } else { ack = (ack >> 15) & 0xf; } @@ -1139,7 +1163,7 @@ static void lynx_irq_handler(int irq, void *dev_id, /* general receive DMA completed */ int stat = reg_read(lynx, DMA1_CHAN_STAT); - printk("-%d- received packet size %d\n", lynx->id, + PRINTD(KERN_DEBUG, lynx->id, "received packet size %d", stat & 0x1fff); if (stat & DMA_CHAN_STAT_SELFID) { @@ -1149,8 +1173,12 @@ static void lynx_irq_handler(int irq, void *dev_id, | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN); } else { - hpsb_packet_received(host, lynx->rcv_page, - stat & 0x1fff); + quadlet_t *q_data = lynx->rcv_page; + if ((*q_data >> 4 & 0xf) == TCODE_READQ_RESPONSE + || (*q_data >> 4 & 0xf) == TCODE_WRITEQ) { + cpu_to_be32s(q_data + 3); + } + hpsb_packet_received(host, q_data, stat & 0x1fff); } run_pcl(lynx, lynx->rcv_pcl_start, 1); @@ -1411,7 +1439,7 @@ static int init_driver() } if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) { - PRINT_G(KERN_ERR, "allocation of char major number %d failed\n", + PRINT_G(KERN_ERR, "allocation of char major number %d failed", PCILYNX_MAJOR); return -EBUSY; } @@ -1453,13 +1481,13 @@ MODULE_SUPPORTED_DEVICE("pcilynx"); void cleanup_module(void) { hpsb_unregister_lowlevel(get_lynx_template()); - PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module\n"); + PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module"); } int init_module(void) { if (hpsb_register_lowlevel(get_lynx_template())) { - PRINT_G(KERN_ERR, "registering failed\n"); + PRINT_G(KERN_ERR, "registering failed"); return -ENXIO; } else { return 0; diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h index 2809bde08321..a65182045f45 100644 --- a/drivers/ieee1394/pcilynx.h +++ b/drivers/ieee1394/pcilynx.h @@ -1,4 +1,3 @@ -#include #define PCILYNX_DRIVER_NAME "pcilynx" #define PCILYNX_MAJOR 177 @@ -462,71 +461,75 @@ inline static void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan) #define PCL_BIGENDIAN (1<<16) +#define _(x) (__constant_cpu_to_be32(x)) + quadlet_t lynx_csr_rom[] = { /* bus info block */ - 0x04040000, /* info/CRC length, CRC */ - 0x31333934, /* 1394 magic number */ - 0xf064a000, /* misc. settings */ - 0x08002850, /* vendor ID, chip ID high */ - 0x0000ffff, /* chip ID low */ + _(0x04040000), /* info/CRC length, CRC */ + _(0x31333934), /* 1394 magic number */ + _(0xf064a000), /* misc. settings */ + _(0x08002850), /* vendor ID, chip ID high */ + _(0x0000ffff), /* chip ID low */ /* root directory */ - 0x00090000, /* CRC length, CRC */ - 0x03080028, /* vendor ID (Texas Instr.) */ - 0x81000009, /* offset to textual ID */ - 0x0c000200, /* node capabilities */ - 0x8d00000e, /* offset to unique ID */ - 0xc7000010, /* offset to module independent info */ - 0x04000000, /* module hardware version */ - 0x81000026, /* offset to textual ID */ - 0x09000000, /* node hardware version */ - 0x81000026, /* offset to textual ID */ + _(0x00090000), /* CRC length, CRC */ + _(0x03080028), /* vendor ID (Texas Instr.) */ + _(0x81000009), /* offset to textual ID */ + _(0x0c000200), /* node capabilities */ + _(0x8d00000e), /* offset to unique ID */ + _(0xc7000010), /* offset to module independent info */ + _(0x04000000), /* module hardware version */ + _(0x81000026), /* offset to textual ID */ + _(0x09000000), /* node hardware version */ + _(0x81000026), /* offset to textual ID */ /* module vendor ID textual */ - 0x00080000, /* CRC length, CRC */ - 0x00000000, - 0x00000000, - 0x54455841, /* "Texas Instruments" */ - 0x5320494e, - 0x53545255, - 0x4d454e54, - 0x53000000, + _(0x00080000), /* CRC length, CRC */ + _(0x00000000), + _(0x00000000), + _(0x54455841), /* "Texas Instruments" */ + _(0x5320494e), + _(0x53545255), + _(0x4d454e54), + _(0x53000000), /* node unique ID leaf */ - 0x00020000, /* CRC length, CRC */ - 0x08002850, /* vendor ID, chip ID high */ - 0x0000ffff, /* chip ID low */ + _(0x00020000), /* CRC length, CRC */ + _(0x08002850), /* vendor ID, chip ID high */ + _(0x0000ffff), /* chip ID low */ /* module dependent info */ - 0x00060000, /* CRC length, CRC */ - 0xb8000006, /* offset to module textual ID */ - 0x81000004, /* ??? textual descriptor */ - 0x39010000, /* SRAM size */ - 0x3a010000, /* AUXRAM size */ - 0x3b000000, /* AUX device */ + _(0x00060000), /* CRC length, CRC */ + _(0xb8000006), /* offset to module textual ID */ + _(0x81000004), /* ??? textual descriptor */ + _(0x39010000), /* SRAM size */ + _(0x3a010000), /* AUXRAM size */ + _(0x3b000000), /* AUX device */ /* module textual ID */ - 0x00050000, /* CRC length, CRC */ - 0x00000000, - 0x00000000, - 0x54534231, /* "TSB12LV21" */ - 0x324c5632, - 0x31000000, + _(0x00050000), /* CRC length, CRC */ + _(0x00000000), + _(0x00000000), + _(0x54534231), /* "TSB12LV21" */ + _(0x324c5632), + _(0x31000000), /* part number */ - 0x00060000, /* CRC length, CRC */ - 0x00000000, - 0x00000000, - 0x39383036, /* "9806000-0001" */ - 0x3030342d, - 0x30303431, - 0x20000001, + _(0x00060000), /* CRC length, CRC */ + _(0x00000000), + _(0x00000000), + _(0x39383036), /* "9806000-0001" */ + _(0x3030342d), + _(0x30303431), + _(0x20000001), /* module hardware version textual */ - 0x00050000, /* CRC length, CRC */ - 0x00000000, - 0x00000000, - 0x5453424b, /* "TSBKPCITST" */ - 0x50434954, - 0x53540000, + _(0x00050000), /* CRC length, CRC */ + _(0x00000000), + _(0x00000000), + _(0x5453424b), /* "TSBKPCITST" */ + _(0x50434954), + _(0x53540000), /* node hardware version textual */ - 0x00050000, /* CRC length, CRC */ - 0x00000000, - 0x00000000, - 0x54534232, /* "TSB21LV03" */ - 0x313c5630, - 0x33000000 + _(0x00050000), /* CRC length, CRC */ + _(0x00000000), + _(0x00000000), + _(0x54534232), /* "TSB21LV03" */ + _(0x313c5630), + _(0x33000000) }; + +#undef _ diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 0e63acb33134..4a994aba5a4c 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -59,7 +59,7 @@ static void free_pending_request(struct pending_request *req) { if (req->ibs) { if (atomic_dec_and_test(&req->ibs->refcount)) { - atomic_sub((req->data[0] >> 16) + 4, &iso_buffer_size); + atomic_sub(req->ibs->data_size, &iso_buffer_size); kfree(req->ibs); } } else if (req->free_data) { @@ -109,6 +109,7 @@ static void queue_complete_cb(struct pending_request *req) } free_tlabel(packet->host, packet->node_id, packet->tlabel); + queue_complete_req(req); } @@ -215,6 +216,7 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data, LIST_HEAD(reqs); if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { + HPSB_INFO("dropped iso packet"); return; } @@ -230,22 +232,23 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data, continue; } + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) break; + if (!ibs) { ibs = kmalloc(sizeof(struct iso_block_store) + length, SLAB_ATOMIC); - if (!ibs) break; + if (!ibs) { + kfree(req); + break; + } atomic_add(length, &iso_buffer_size); atomic_set(&ibs->refcount, 0); + ibs->data_size = length; memcpy(ibs->data, data, length); } - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) { - kfree(ibs); - break; - } - atomic_inc(&ibs->refcount); req->file_info = fi; @@ -270,6 +273,75 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data, } } +static void fcp_request(struct hpsb_host *host, int nodeid, int direction, + int cts, u8 *data, unsigned int length) +{ + unsigned long flags; + struct list_head *lh; + struct host_info *hi; + struct file_info *fi; + struct pending_request *req; + struct iso_block_store *ibs = NULL; + LIST_HEAD(reqs); + + if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { + HPSB_INFO("dropped fcp request"); + return; + } + + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(host); + + if (hi != NULL) { + for (lh = hi->file_info_list.next; lh != &hi->file_info_list; + lh = lh->next) { + fi = list_entry(lh, struct file_info, list); + + if (!fi->fcp_buffer) { + continue; + } + + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) break; + + if (!ibs) { + ibs = kmalloc(sizeof(struct iso_block_store) + + length, SLAB_ATOMIC); + if (!ibs) { + kfree(req); + break; + } + + atomic_add(length, &iso_buffer_size); + atomic_set(&ibs->refcount, 0); + ibs->data_size = length; + memcpy(ibs->data, data, length); + } + + atomic_inc(&ibs->refcount); + + req->file_info = fi; + req->ibs = ibs; + req->data = ibs->data; + req->req.type = RAW1394_REQ_FCP_REQUEST; + req->req.generation = get_hpsb_generation(); + req->req.misc = nodeid | (direction << 16); + req->req.recvb = (quadlet_t *)fi->fcp_buffer; + req->req.length = length; + + list_add_tail(&req->list, &reqs); + } + } + spin_unlock_irqrestore(&host_info_lock, flags); + + lh = reqs.next; + while (lh != &reqs) { + req = list_entry(lh, struct pending_request, list); + lh = lh->next; + queue_complete_req(req); + } +} + static int dev_read(struct file *file, char *buffer, size_t count, loff_t *offset_is_ignored) @@ -455,8 +527,28 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) spin_unlock(&host_info_lock); } +static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) +{ + if (req->req.misc) { + if (fi->fcp_buffer) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->fcp_buffer = (u8 *)req->req.recvb; + } + } else { + if (!fi->fcp_buffer) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->fcp_buffer = NULL; + } + } + + req->req.length = 0; + queue_complete_req(req); +} + static int handle_local_request(struct file_info *fi, - struct pending_request *req) + struct pending_request *req, int node) { u64 addr = req->req.address & 0xffffffffffffULL; @@ -466,7 +558,7 @@ static int handle_local_request(struct file_info *fi, switch (req->req.type) { case RAW1394_REQ_ASYNC_READ: - req->req.error = highlevel_read(fi->host, req->data, addr, + req->req.error = highlevel_read(fi->host, node, req->data, addr, req->req.length); break; @@ -477,8 +569,8 @@ static int handle_local_request(struct file_info *fi, break; } - req->req.error = highlevel_write(fi->host, req->data, addr, - req->req.length); + req->req.error = highlevel_write(fi->host, node, req->data, + addr, req->req.length); req->req.length = 0; break; @@ -503,14 +595,16 @@ static int handle_local_request(struct file_info *fi, } if (req->req.length == 8) { - req->req.error = highlevel_lock(fi->host, req->data, - addr, req->data[1], + req->req.error = highlevel_lock(fi->host, node, + req->data, addr, + req->data[1], req->data[0], req->req.misc); req->req.length = 4; } else { - req->req.error = highlevel_lock(fi->host, req->data, - addr, req->data[0], 0, + req->req.error = highlevel_lock(fi->host, node, + req->data, addr, + req->data[0], 0, req->req.misc); } break; @@ -539,28 +633,27 @@ static int handle_remote_request(struct file_info *fi, if (!packet) return -ENOMEM; req->data = &packet->header[3]; - } else if ((req->req.length % 4) == 0) { + } else { packet = hpsb_make_readbpacket(fi->host, node, addr, req->req.length); if (!packet) return -ENOMEM; req->data = packet->data; - } else { - req->req.error = RAW1394_ERROR_UNTIDY_LEN; } break; case RAW1394_REQ_ASYNC_WRITE: if (req->req.length == 4) { - packet = hpsb_make_writeqpacket(fi->host, node, addr, - 0); - if (!packet) return -ENOMEM; + quadlet_t x; - if (copy_from_user(&packet->header[3], req->req.sendb, - 4)) { + if (copy_from_user(&x, req->req.sendb, 4)) { req->req.error = RAW1394_ERROR_MEMFAULT; } - } else if ((req->req.length % 4) == 0) { + + packet = hpsb_make_writeqpacket(fi->host, node, addr, + x); + if (!packet) return -ENOMEM; + } else { packet = hpsb_make_writebpacket(fi->host, node, addr, req->req.length); if (!packet) return -ENOMEM; @@ -569,8 +662,6 @@ static int handle_remote_request(struct file_info *fi, req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; } - } else { - req->req.error = RAW1394_ERROR_UNTIDY_LEN; } req->req.length = 0; break; @@ -649,6 +740,11 @@ static int state_connected(struct file_info *fi, struct pending_request *req) return sizeof(struct raw1394_request); } + if (req->req.type == RAW1394_REQ_FCP_LISTEN) { + handle_fcp_listen(fi, req); + return sizeof(struct raw1394_request); + } + if (req->req.length == 0) { req->req.error = RAW1394_ERROR_INVALID_ARG; queue_complete_req(req); @@ -656,7 +752,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) } if (fi->host->node_id == node) { - return handle_local_request(fi, req); + return handle_local_request(fi, req, node); } return handle_remote_request(fi, req, node); @@ -806,10 +902,11 @@ static int dev_release(struct inode *inode, struct file *file) } static struct hpsb_highlevel_ops hl_ops = { - add_host, - remove_host, - host_reset, - iso_receive + add_host: add_host, + remove_host: remove_host, + host_reset: host_reset, + iso_receive: iso_receive, + fcp_request: fcp_request, }; static struct file_operations file_ops = { diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h index b1b0e4b90586..f23bfc0512a0 100644 --- a/drivers/ieee1394/raw1394.h +++ b/drivers/ieee1394/raw1394.h @@ -5,7 +5,7 @@ #define RAW1394_DEVICE_MAJOR 171 #define RAW1394_DEVICE_NAME "raw1394" -#define RAW1394_KERNELAPI_VERSION 1 +#define RAW1394_KERNELAPI_VERSION 2 /* state: opened */ #define RAW1394_REQ_INITIALIZE 1 @@ -21,10 +21,12 @@ #define RAW1394_REQ_LOCK64 103 #define RAW1394_REQ_ISO_LISTEN 200 +#define RAW1394_REQ_FCP_LISTEN 201 /* kernel to user */ #define RAW1394_REQ_BUS_RESET 10000 #define RAW1394_REQ_ISO_RECEIVE 10001 +#define RAW1394_REQ_FCP_REQUEST 10002 /* error codes */ #define RAW1394_ERROR_NONE 0 @@ -67,6 +69,7 @@ struct raw1394_khost_list { struct iso_block_store { atomic_t refcount; + size_t data_size; quadlet_t data[0]; }; @@ -83,6 +86,8 @@ struct file_info { spinlock_t reqlists_lock; wait_queue_head_t poll_wait_complete; + u8 *fcp_buffer; + u64 listen_channels; quadlet_t *iso_buffer; size_t iso_buffer_length; diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c index 091702d156ac..f1641a33a51b 100644 --- a/drivers/sbus/char/sunmouse.c +++ b/drivers/sbus/char/sunmouse.c @@ -69,7 +69,6 @@ struct sun_mouse { unsigned char prev_state; /* Previous button state */ int delta_x; /* Current delta-x */ int delta_y; /* Current delta-y */ - int present; int ready; /* set if there if data is available */ int active; /* set if device is open */ int vuid_mode; /* VUID_NATIVE or VUID_FIRM_EVENT */ @@ -382,8 +381,6 @@ sun_mouse_open(struct inode * inode, struct file * file) { if(sunmouse.active++) return 0; - if(!sunmouse.present) - return -EINVAL; sunmouse.ready = sunmouse.delta_x = sunmouse.delta_y = 0; sunmouse.button_state = 0x80; sunmouse.vuid_mode = VUID_NATIVE; @@ -555,11 +552,8 @@ static struct miscdevice sun_mouse_mouse = { SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops }; -int __init sun_mouse_init(void) +void sun_mouse_zsinit(void) { - if (!sunmouse.present) - return -ENODEV; - printk("Sun Mouse-Systems mouse driver version 1.00\n"); sunmouse.ready = sunmouse.active = 0; @@ -568,11 +562,4 @@ int __init sun_mouse_init(void) sunmouse.button_state = 0x80; init_waitqueue_head(&sunmouse.proc_list); sunmouse.byte = 69; - return 0; -} - -void -sun_mouse_zsinit(void) -{ - sunmouse.present = 1; } diff --git a/drivers/sbus/char/sunserial.c b/drivers/sbus/char/sunserial.c index 9719f625a217..e58eb1ef7800 100644 --- a/drivers/sbus/char/sunserial.c +++ b/drivers/sbus/char/sunserial.c @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.74 1999/12/15 22:30:23 davem Exp $ +/* $Id: sunserial.c,v 1.75 2000/03/22 02:45:36 davem Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -67,6 +67,8 @@ int rs_init(void) return err; } +__initcall(rs_init); + void __init rs_kgdb_hook(int channel) { rs_ops.rs_kgdb_hook(channel); diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c index 190a4bcb9890..8e9c314baa72 100644 --- a/drivers/scsi/qlogicisp.c +++ b/drivers/scsi/qlogicisp.c @@ -21,6 +21,7 @@ */ #include +#include #include #include #include diff --git a/drivers/sound/sb_card.c.rej b/drivers/sound/sb_card.c.rej deleted file mode 100644 index 981347ffc0af..000000000000 --- a/drivers/sound/sb_card.c.rej +++ /dev/null @@ -1,290 +0,0 @@ -*************** -*** 399,405 **** - /* @X@0001:mpu - */ - -- #ifdef CONFIG_MIDI - if((mpu_dev = isapnp_find_dev(bus, - ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL))) - { ---- 361,366 ---- - /* @X@0001:mpu - */ - - if((mpu_dev = isapnp_find_dev(bus, - ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL))) - { -*************** -*** 413,583 **** - } - else - printk(KERN_ERR "sb: DT0197H panic: mpu not found\n"); -- #endif -- -- -- /* @P@:Gameport -- */ -- -- if((jp_dev = isapnp_find_dev(bus, -- ISAPNP_VENDOR('@','P','@'), ISAPNP_FUNCTION(0x0001), NULL))) -- { -- jp_dev->prepare(jp_dev); -- -- if((jp_dev = activate_dev("DT0197H", "gameport", jp_dev))) -- show_base("DT0197H", "gameport", &jp_dev->resource[0]); -- } -- else -- printk(KERN_ERR "sb: DT0197H panic: gameport not found\n"); -- -- /* @H@0001:OPL3 -- */ -- -- #if defined(CONFIG_SOUND_YM3812) || defined(CONFIG_SOUND_YM3812_MODULE) -- if((wss_dev = isapnp_find_dev(bus, -- ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), NULL))) -- { -- wss_dev->prepare(wss_dev); -- -- /* Let's disable IRQ and DMA for WSS device */ -- -- wss_dev->irq_resource[0].flags = 0; -- wss_dev->dma_resource[0].flags = 0; -- -- if((wss_dev = activate_dev("DT0197H", "opl3", wss_dev))) -- show_base("DT0197H", "opl3", &wss_dev->resource[0]); -- } -- else -- printk(KERN_ERR "sb: DT0197H panic: opl3 not found\n"); -- #endif - - printk(KERN_INFO "sb: DT0197H mail reports to Torsten Werner \n"); - - return(sb_dev); - } - -- /* Specific support for awe will be dropped when: -- * a) The new awe_wawe driver with PnP support will be introduced in the kernel -- * b) The joystick driver will support PnP - a little patch is available from me....hint, hint :-) -- */ -- -- static struct pci_dev *sb_init_awe(struct pci_bus *bus, struct pci_dev *card, struct address_info *hw_config, struct address_info *mpu_config) - { -- /* CTL0042:Audio SB64 -- * CTL0031:Audio SB32 -- * CTL0045:Audio SB64 - */ - -- if( (sb_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), NULL)) || -- (sb_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), NULL)) || -- (sb_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), NULL)) ) - { - sb_dev->prepare(sb_dev); - -- if((sb_dev = activate_dev("AWE", "sb", sb_dev))) - { - hw_config->io_base = sb_dev->resource[0].start; - hw_config->irq = sb_dev->irq_resource[0].start; -- hw_config->dma = sb_dev->dma_resource[0].start; -- hw_config->dma2 = sb_dev->dma_resource[1].start; -- -- mpu_config->io_base = sb_dev->resource[1].start; - -- show_base("AWE", "sb", &sb_dev->resource[0]); -- show_base("AWE", "mpu", &sb_dev->resource[1]); -- show_base("AWE", "opl3", &sb_dev->resource[2]); - } -- else -- return(NULL); -- } -- else -- printk(KERN_ERR "sb: AWE panic: sb base not found\n"); -- - -- /* CTL7002:Game SB64 -- * CTL7001:Game SB32 -- */ -- -- if( (jp_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x7002), NULL)) || -- (jp_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x7001), NULL)) ) -- { -- jp_dev->prepare(jp_dev); -- -- if((jp_dev = activate_dev("AWE", "gameport", jp_dev))) -- show_base("AWE", "gameport", &jp_dev->resource[0]); - } - else -- printk(KERN_ERR "sb: AWE panic: gameport not found\n"); -- - -- /* CTL0022:WaveTable SB64 -- * CTL0021:WaveTable SB32 -- * CTL0023:WaveTable Sb64 - */ - -- if( nosbwave == 0 && -- ( ( wt_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0023), NULL)) || -- ( wt_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0022), NULL)) || -- ( wt_dev = isapnp_find_dev(bus, ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0021), NULL)) )) - { -- wt_dev->prepare(wt_dev); -- -- if((wt_dev = activate_dev("AWE", "wavetable", wt_dev))) - { -- show_base("AWE", "wavetable", &wt_dev->resource[0]); -- show_base("AWE", "wavetable", &wt_dev->resource[1]); -- show_base("AWE", "wavetable", &wt_dev->resource[2]); - } - } - else -- printk(KERN_ERR "sb: AWE panic: wavetable not found\n"); - -- printk(KERN_INFO "sb: AWE mail reports to Alessandro Zummo \n"); - - return(sb_dev); - } - -- #define SBF_DEV 0x01 -- - - static struct { unsigned short vendor, function, flags; struct pci_dev * (*initfunc)(struct pci_bus *, struct pci_dev *, struct address_info *, struct address_info *); char *name; } -- isapnp_sb_list[] __initdata = { - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, -- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0, &sb_init_awe, "Sound Blaster 32" }, -- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0039), 0, &sb_init_awe, "Sound Blaster AWE 32" }, -- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x009D), 0, &sb_init_awe, "Sound Blaster AWE 64" }, -- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x00C5), 0, &sb_init_awe, "Sound Blaster AWE 64" }, -- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x00E4), 0, &sb_init_awe, "Sound Blaster AWE 64" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), SBF_DEV, &sb_init_ess, "ESS 1688" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), SBF_DEV, &sb_init_ess, "ESS 1868" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), SBF_DEV, &sb_init_ess, "ESS 1868" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), SBF_DEV, &sb_init_ess, "ESS 1869" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), SBF_DEV, &sb_init_ess, "ESS 1878" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), SBF_DEV, &sb_init_ess, "ESS 1879" }, -- {ISAPNP_VENDOR('C','M','I'), ISAPNP_FUNCTION(0x0001), 0, &sb_init_cmi, "CMI 8330 SoundPRO" }, -- {ISAPNP_VENDOR('R','W','B'), ISAPNP_FUNCTION(0x1688), 0, &sb_init_diamond, "Diamond DT0197H" }, - {0} - }; - -- static int __init sb_init_isapnp(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, struct pci_dev *card, int slot) - { - struct pci_dev *idev = NULL; - - /* You missed the init func? That's bad. */ -- if(isapnp_sb_list[slot].initfunc) - { -- char *busname = bus->name[0] ? bus->name : isapnp_sb_list[slot].name; - - printk(KERN_INFO "sb: %s detected\n", busname); - - /* Initialize this baby. */ - -- if((idev = isapnp_sb_list[slot].initfunc(bus, card, hw_config, mpu_config))) - { - /* We got it. */ - ---- 374,473 ---- - } - else - printk(KERN_ERR "sb: DT0197H panic: mpu not found\n"); - - printk(KERN_INFO "sb: DT0197H mail reports to Torsten Werner \n"); - - return(sb_dev); - } - -+ static struct pci_dev *sb_init_als(struct pci_bus *bus, struct pci_dev *card, struct address_info *hw_config, struct address_info *mpu_config) - { -+ /* -+ * ALS 100 -+ * very similar to both ones above -+ */ -+ -+ /* @@@0001:Soundblaster. - */ - -+ if((sb_dev = isapnp_find_dev(bus, -+ ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), NULL))) - { - sb_dev->prepare(sb_dev); - -+ if((sb_dev = activate_dev("ALS100", "sb", sb_dev))) - { - hw_config->io_base = sb_dev->resource[0].start; - hw_config->irq = sb_dev->irq_resource[0].start; -+ hw_config->dma = sb_dev->dma_resource[1].start; -+ hw_config->dma2 = sb_dev->dma_resource[0].start; - -+ show_base("ALS100", "sb", &sb_dev->resource[0]); - } - -+ if(!sb_dev) return(NULL); - } - else -+ printk(KERN_ERR "sb: ALS100 panic: sb base not found\n"); - -+ /* @X@0001:mpu - */ - -+ if((mpu_dev = isapnp_find_dev(bus, -+ ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL))) - { -+ mpu_dev->prepare(mpu_dev); -+ -+ if((mpu_dev = activate_dev("ALS100", "mpu", mpu_dev))) - { -+ show_base("ALS100", "mpu", &mpu_dev->resource[0]); -+ mpu_config->io_base = mpu_dev->resource[0].start; - } - } - else -+ printk(KERN_ERR "sb: ALS100 panic: mpu not found\n"); - -+ printk(KERN_INFO "sb: ALS100 mail reports to Torsten Werner \n"); - - return(sb_dev); - } - -+ #define SBF_DEV 0x01 /* Please notice that cards without this flag set are on top in the list */ - - static struct { unsigned short vendor, function, flags; struct pci_dev * (*initfunc)(struct pci_bus *, struct pci_dev *, struct address_info *, struct address_info *); char *name; } -+ sb_isapnp_list[] __initdata = { -+ {ISAPNP_VENDOR('C','M','I'), ISAPNP_FUNCTION(0x0001), 0, &sb_init_cmi, "CMI 8330 SoundPRO" }, -+ {ISAPNP_VENDOR('R','W','B'), ISAPNP_FUNCTION(0x1688), 0, &sb_init_diamond, "Diamond DT0197H" }, -+ {ISAPNP_VENDOR('A','L','S'), ISAPNP_FUNCTION(0x0001), 0, &sb_init_als, "ALS 100" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), SBF_DEV, &sb_init_generic, "Sound Blaster 16" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), SBF_DEV, &sb_init_ess, "ESS 1688" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), SBF_DEV, &sb_init_ess, "ESS 1868" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), SBF_DEV, &sb_init_ess, "ESS 1868" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), SBF_DEV, &sb_init_ess, "ESS 1869" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), SBF_DEV, &sb_init_ess, "ESS 1878" }, - {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), SBF_DEV, &sb_init_ess, "ESS 1879" }, - {0} - }; - -+ static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, struct pci_dev *card, int slot) - { - struct pci_dev *idev = NULL; - - /* You missed the init func? That's bad. */ -+ if(sb_isapnp_list[slot].initfunc) - { -+ char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name; - - printk(KERN_INFO "sb: %s detected\n", busname); - - /* Initialize this baby. */ - -+ if((idev = sb_isapnp_list[slot].initfunc(bus, card, hw_config, mpu_config))) - { - /* We got it. */ - diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c index 5e4d45a9ebfa..9cec20abfa4f 100644 --- a/drivers/video/cgthreefb.c +++ b/drivers/video/cgthreefb.c @@ -1,4 +1,4 @@ -/* $Id: cgthreefb.c,v 1.8 1999/11/19 09:57:08 davem Exp $ +/* $Id: cgthreefb.c,v 1.9 2000/03/19 04:20:44 anton Exp $ * cgthreefb.c: CGthree frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -114,9 +114,9 @@ static void cg3_blank (struct fb_info_sbusfb *fb) u8 tmp; spin_lock_irqsave(&fb->lock, flags); - tmp = sbus_readl(&fb->s.cg3.regs->control); + tmp = sbus_readb(&fb->s.cg3.regs->control); tmp &= ~CG3_CR_ENABLE_VIDEO; - sbus_writel(tmp, &fb->s.cg3.regs->control); + sbus_writeb(tmp, &fb->s.cg3.regs->control); spin_unlock_irqrestore(&fb->lock, flags); } @@ -126,9 +126,9 @@ static void cg3_unblank (struct fb_info_sbusfb *fb) u8 tmp; spin_lock_irqsave(&fb->lock, flags); - tmp = sbus_readl(&fb->s.cg3.regs->control); + tmp = sbus_readb(&fb->s.cg3.regs->control); tmp |= CG3_CR_ENABLE_VIDEO; - sbus_writel(tmp, &fb->s.cg3.regs->control); + sbus_writeb(tmp, &fb->s.cg3.regs->control); spin_unlock_irqrestore(&fb->lock, flags); } diff --git a/fs/nfs/flushd.c b/fs/nfs/flushd.c index 66476bca660f..d36c3a9aecee 100644 --- a/fs/nfs/flushd.c +++ b/fs/nfs/flushd.c @@ -22,6 +22,7 @@ * Copyright (C) 1999, 2000, Trond Myklebust */ +#include #include #include #include diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d7dec8fed234..96dfebe6835b 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -46,6 +46,7 @@ * Copyright (C) 1996, 1997, Olaf Kirch */ +#include #include #include #include diff --git a/fs/pipe.c b/fs/pipe.c index 653110847a46..f25f5e514a1f 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -284,7 +284,7 @@ pipe_poll(struct file *filp, poll_table *wait) /* Reading only -- no need for aquiring the semaphore. */ mask = POLLIN | POLLRDNORM; - if (PIPE_FREE(*inode) >= PIPE_BUF) + if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode)) mask |= POLLHUP; diff --git a/include/asm-sparc/asm_offsets.h b/include/asm-sparc/asm_offsets.h index 3bbf39b20942..57c2ffd9bd07 100644 --- a/include/asm-sparc/asm_offsets.h +++ b/include/asm-sparc/asm_offsets.h @@ -142,21 +142,21 @@ #define ASIZ_task_cap_inheritable 0x00000004 #define AOFF_task_cap_permitted 0x000001c8 #define ASIZ_task_cap_permitted 0x00000004 -#define AOFF_task_user 0x000001cc +#define AOFF_task_user 0x000001d0 #define ASIZ_task_user 0x00000004 -#define AOFF_task_rlim 0x000001d0 +#define AOFF_task_rlim 0x000001d4 #define ASIZ_task_rlim 0x00000050 -#define AOFF_task_used_math 0x00000220 +#define AOFF_task_used_math 0x00000224 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_comm 0x00000222 +#define AOFF_task_comm 0x00000226 #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x00000234 +#define AOFF_task_link_count 0x00000238 #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x00000238 +#define AOFF_task_tty 0x0000023c #define ASIZ_task_tty 0x00000004 -#define AOFF_task_semundo 0x0000023c +#define AOFF_task_semundo 0x00000240 #define ASIZ_task_semundo 0x00000004 -#define AOFF_task_semsleeping 0x00000240 +#define AOFF_task_semsleeping 0x00000244 #define ASIZ_task_semsleeping 0x00000004 #define AOFF_task_thread 0x00000248 #define ASIZ_task_thread 0x00000380 @@ -423,49 +423,49 @@ #define ASIZ_task_cap_inheritable 0x00000004 #define AOFF_task_cap_permitted 0x000002c4 #define ASIZ_task_cap_permitted 0x00000004 -#define AOFF_task_user 0x000002c8 +#define AOFF_task_user 0x000002cc #define ASIZ_task_user 0x00000004 -#define AOFF_task_rlim 0x000002cc +#define AOFF_task_rlim 0x000002d0 #define ASIZ_task_rlim 0x00000050 -#define AOFF_task_used_math 0x0000031c +#define AOFF_task_used_math 0x00000320 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_comm 0x0000031e +#define AOFF_task_comm 0x00000322 #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x00000330 +#define AOFF_task_link_count 0x00000334 #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x00000334 +#define AOFF_task_tty 0x00000338 #define ASIZ_task_tty 0x00000004 -#define AOFF_task_semundo 0x00000338 +#define AOFF_task_semundo 0x0000033c #define ASIZ_task_semundo 0x00000004 -#define AOFF_task_semsleeping 0x0000033c +#define AOFF_task_semsleeping 0x00000340 #define ASIZ_task_semsleeping 0x00000004 -#define AOFF_task_thread 0x00000340 +#define AOFF_task_thread 0x00000348 #define ASIZ_task_thread 0x00000380 -#define AOFF_task_fs 0x000006c0 +#define AOFF_task_fs 0x000006c8 #define ASIZ_task_fs 0x00000004 -#define AOFF_task_files 0x000006c4 +#define AOFF_task_files 0x000006cc #define ASIZ_task_files 0x00000004 -#define AOFF_task_sigmask_lock 0x000006c8 +#define AOFF_task_sigmask_lock 0x000006d0 #define ASIZ_task_sigmask_lock 0x00000008 -#define AOFF_task_sig 0x000006d0 +#define AOFF_task_sig 0x000006d8 #define ASIZ_task_sig 0x00000004 -#define AOFF_task_signal 0x000006d4 +#define AOFF_task_signal 0x000006dc #define ASIZ_task_signal 0x00000008 -#define AOFF_task_blocked 0x000006dc +#define AOFF_task_blocked 0x000006e4 #define ASIZ_task_blocked 0x00000008 -#define AOFF_task_sigqueue 0x000006e4 +#define AOFF_task_sigqueue 0x000006ec #define ASIZ_task_sigqueue 0x00000004 -#define AOFF_task_sigqueue_tail 0x000006e8 +#define AOFF_task_sigqueue_tail 0x000006f0 #define ASIZ_task_sigqueue_tail 0x00000004 -#define AOFF_task_sas_ss_sp 0x000006ec +#define AOFF_task_sas_ss_sp 0x000006f4 #define ASIZ_task_sas_ss_sp 0x00000004 -#define AOFF_task_sas_ss_size 0x000006f0 +#define AOFF_task_sas_ss_size 0x000006f8 #define ASIZ_task_sas_ss_size 0x00000004 -#define AOFF_task_parent_exec_id 0x000006f4 +#define AOFF_task_parent_exec_id 0x000006fc #define ASIZ_task_parent_exec_id 0x00000004 -#define AOFF_task_self_exec_id 0x000006f8 +#define AOFF_task_self_exec_id 0x00000700 #define ASIZ_task_self_exec_id 0x00000004 -#define AOFF_task_exit_sem 0x000006fc +#define AOFF_task_exit_sem 0x00000704 #define ASIZ_task_exit_sem 0x00000024 #define AOFF_mm_mmap 0x00000000 #define ASIZ_mm_mmap 0x00000004 diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index b0543fffb870..8925923b0de3 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.92 2000/03/02 20:37:37 davem Exp $ */ +/* $Id: pgtable.h,v 1.93 2000/03/21 01:04:53 anton Exp $ */ #ifndef _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H @@ -96,9 +96,12 @@ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd) #define VMALLOC_START (0xfe300000) #define VMALLOC_END ~0x0UL -#define pte_ERROR(e) __builtin_trap() -#define pmd_ERROR(e) __builtin_trap() -#define pgd_ERROR(e) __builtin_trap() +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) +#define pmd_ERROR(e) \ + printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) BTFIXUPDEF_INT(page_none) BTFIXUPDEF_INT(page_shared) diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index 757f43c4ddbe..7211c7d81846 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.32 2000/03/15 07:19:28 davem Exp $ */ +/* $Id: page.h,v 1.33 2000/03/22 02:48:04 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -96,8 +96,7 @@ typedef unsigned long iopgprot_t; #ifndef __ASSEMBLY__ /* Do prdele, look what happens to be in %g4... */ -register unsigned long page_offset asm("g4"); -#define PAGE_OFFSET page_offset +register unsigned long PAGE_OFFSET asm("g4"); #else #define PAGE_OFFSET 0xFFFFF80000000000 #endif diff --git a/include/linux/atm_idt77105.h b/include/linux/atm_idt77105.h index 70e9e6e590ae..05621cf20709 100644 --- a/include/linux/atm_idt77105.h +++ b/include/linux/atm_idt77105.h @@ -9,6 +9,7 @@ #include #include +#include /* * Structure for IDT77105_GETSTAT and IDT77105_GETSTATZ ioctls. @@ -21,20 +22,7 @@ struct idt77105_stats { __u32 rx_hec_errors; /* Header Error Check errors on receive */ }; -#define IDT77105_GETLOOP _IOW('a',ATMIOC_PHYPRV,struct atmif_sioc) /* get loopback mode */ -#define IDT77105_SETLOOP _IOW('a',ATMIOC_PHYPRV+1,struct atmif_sioc) /* set loopback mode */ #define IDT77105_GETSTAT _IOW('a',ATMIOC_PHYPRV+2,struct atmif_sioc) /* get stats */ #define IDT77105_GETSTATZ _IOW('a',ATMIOC_PHYPRV+3,struct atmif_sioc) /* get stats and zero */ - -/* - * TODO: what we need is a global loopback mode get/set ioctl for - * all devices, not these device-specific hacks -- Greg Banks - */ -#define IDT77105_LM_NONE 0 /* no loopback */ -#define IDT77105_LM_DIAG 1 /* diagnostic (i.e. loop TX to RX) - * (a.k.a. local loopback) */ -#define IDT77105_LM_LOOP 2 /* line (i.e. loop RX to TX) - * (a.k.a. remote loopback) */ - #endif diff --git a/include/linux/atm_suni.h b/include/linux/atm_suni.h index 2e6a01a61805..84f3aab54468 100644 --- a/include/linux/atm_suni.h +++ b/include/linux/atm_suni.h @@ -1,19 +1,12 @@ /* atm_suni.h - Driver-specific declarations of the SUNI driver (for use by driver-specific utilities) */ -/* Written 1998 by Werner Almesberger, EPFL ICA */ +/* Written 1998,2000 by Werner Almesberger, EPFL ICA */ #ifndef LINUX_ATM_SUNI_H #define LINUX_ATM_SUNI_H -#include - -#define SUNI_GETLOOP _IOR('a',ATMIOC_PHYPRV,int) /* get loopback mode */ -#define SUNI_SETLOOP _IO('a',ATMIOC_PHYPRV+1) /* set loopback mode */ - -#define SUNI_LM_NONE 0 /* no loopback */ -#define SUNI_LM_DIAG 1 /* diagnostic (i.e. loop TX to RX) */ -#define SUNI_LM_LOOP 2 /* line (i.e. loop RX to TX) */ +/* everything obsoleted */ #endif diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 95e97de35f32..0a9eb9762f5f 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -1,6 +1,6 @@ /* atmdev.h - ATM device driver declarations and various related items */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #ifndef LINUX_ATMDEV_H @@ -20,6 +20,8 @@ SONET overhead: /270*260 (9 section, 1 path) bits per cell: /8/53 max cell rate: 353207.547 cells/sec */ +#define ATM_25_PCR ((25600000/8-8000)/54) + /* 25 Mbps ATM cell rate (59111) */ #define ATM_PDU_OVHD 0 /* number of bytes to charge against buffer quota per PDU */ @@ -27,10 +29,17 @@ #define ATM_SD(s) ((s)->sk->protinfo.af_atm) +#define __AAL_STAT_ITEMS \ + __HANDLE_ITEM(tx); /* TX okay */ \ + __HANDLE_ITEM(tx_err); /* TX errors */ \ + __HANDLE_ITEM(rx); /* RX okay */ \ + __HANDLE_ITEM(rx_err); /* RX errors */ \ + __HANDLE_ITEM(rx_drop); /* RX out of memory */ + struct atm_aal_stats { - int tx,tx_err; /* TX okay and errors */ - int rx,rx_err; /* RX okay and errors */ - int rx_drop; /* RX out of memory */ +#define __HANDLE_ITEM(i) int i + __AAL_STAT_ITEMS +#undef __HANDLE_ITEM }; @@ -69,12 +78,53 @@ struct atm_dev_stats { /* get AAL layer statistics */ #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) /* get AAL layer statistics and zero */ +#define ATM_GETLOOP _IOW('a',ATMIOC_SARCOM+2,struct atmif_sioc) + /* get loopback mode */ +#define ATM_SETLOOP _IOW('a',ATMIOC_SARCOM+3,struct atmif_sioc) + /* set loopback mode */ +#define ATM_QUERYLOOP _IOW('a',ATMIOC_SARCOM+4,struct atmif_sioc) + /* query supported loopback modes */ #define ATM_SETSC _IOW('a',ATMIOC_SPECIAL+1,int) /* enable or disable single-copy */ /* for ATM_GETTYPE */ #define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */ +/* + * Loopback modes for ATM_{PHY,SAR}_{GET,SET}LOOP + */ + +/* Point of loopback CPU-->SAR-->PHY-->line--> ... */ +#define __ATM_LM_NONE 0 /* no loop back ^ ^ ^ ^ */ +#define __ATM_LM_AAL 1 /* loop back PDUs --' | | | */ +#define __ATM_LM_ATM 2 /* loop back ATM cells ---' | | */ +/* RESERVED 4 loop back on PHY side ---' */ +#define __ATM_LM_PHY 8 /* loop back bits (digital) ----' | */ +#define __ATM_LM_ANALOG 16 /* loop back the analog signal --------' */ + +/* Direction of loopback */ +#define __ATM_LM_MKLOC(n) ((n)) /* Local (i.e. loop TX to RX) */ +#define __ATM_LM_MKRMT(n) ((n) << 8) /* Remote (i.e. loop RX to TX) */ + +#define __ATM_LM_XTLOC(n) ((n) & 0xff) +#define __ATM_LM_XTRMT(n) (((n) >> 8) & 0xff) + +#define ATM_LM_NONE 0 /* no loopback */ + +#define ATM_LM_LOC_AAL __ATM_LM_MKLOC(__ATM_LM_AAL) +#define ATM_LM_LOC_ATM __ATM_LM_MKLOC(__ATM_LM_ATM) +#define ATM_LM_LOC_PHY __ATM_LM_MKLOC(__ATM_LM_PHY) +#define ATM_LM_LOC_ANALOG __ATM_LM_MKLOC(__ATM_LM_ANALOG) + +#define ATM_LM_RMT_AAL __ATM_LM_MKRMT(__ATM_LM_AAL) +#define ATM_LM_RMT_ATM __ATM_LM_MKRMT(__ATM_LM_ATM) +#define ATM_LM_RMT_PHY __ATM_LM_MKRMT(__ATM_LM_PHY) +#define ATM_LM_RMT_ANALOG __ATM_LM_MKRMT(__ATM_LM_ANALOG) + +/* + * Note: ATM_LM_LOC_* and ATM_LM_RMT_* can be combined, provided that + * __ATM_LM_XTLOC(x) <= __ATM_LM_XTRMT(x) + */ struct atm_iobuf { @@ -132,7 +182,9 @@ struct atm_cirange { "SESSION", "HASSAP", "BOUND", "CLOSE" -#ifdef __KERNEL__ +#ifndef __KERNEL__ +#undef __AAL_STAT_ITEMS +#else #include /* wait_queue_head_t */ #include /* struct timeval */ @@ -147,39 +199,56 @@ struct atm_cirange { #endif -#define ATM_VF_ADDR 1 /* Address is in use. Set by anybody, cleared +struct k_atm_aal_stats { +#define __HANDLE_ITEM(i) atomic_t i + __AAL_STAT_ITEMS +#undef __HANDLE_ITEM +}; + + +struct k_atm_dev_stats { + struct k_atm_aal_stats aal0; + struct k_atm_aal_stats aal34; + struct k_atm_aal_stats aal5; +}; + + +enum { + ATM_VF_ADDR, /* Address is in use. Set by anybody, cleared by device driver. */ -#define ATM_VF_READY 2 /* VC is ready to transfer data. Set by device + ATM_VF_READY, /* VC is ready to transfer data. Set by device driver, cleared by anybody. */ -#define ATM_VF_PARTIAL 4 /* resources are bound to PVC (partial PVC + ATM_VF_PARTIAL, /* resources are bound to PVC (partial PVC setup), controlled by socket layer */ -#define ATM_VF_BOUND 16384 /* local SAP is set, controlled by SVC socket - layer */ -#define ATM_VF_REGIS 8 /* registered with demon, controlled by SVC + ATM_VF_REGIS, /* registered with demon, controlled by SVC socket layer */ -#define ATM_VF_RELEASED 16 /* demon has indicated/requested release, + ATM_VF_BOUND, /* local SAP is set, controlled by SVC socket + layer */ + ATM_VF_RELEASED, /* demon has indicated/requested release, controlled by SVC socket layer */ -#define ATM_VF_HASQOS 32 /* QOS parameters have been set */ -#define ATM_VF_LISTEN 64 /* socket is used for listening */ -#define ATM_VF_META 128 /* SVC socket isn't used for normal data + ATM_VF_HASQOS, /* QOS parameters have been set */ + ATM_VF_LISTEN, /* socket is used for listening */ + ATM_VF_META, /* SVC socket isn't used for normal data traffic and doesn't depend on signaling to be available */ - /* 256; unused */ - /* 512; unused */ - /* 1024; unused */ - /* 2048; unused */ -#define ATM_VF_SESSION 4096 /* VCC is p2mp session control descriptor */ -#define ATM_VF_HASSAP 8192 /* SAP has been set */ -#define ATM_VF_CLOSE 32768 /* asynchronous close - treat like VF_RELEASED*/ + ATM_VF_SESSION, /* VCC is p2mp session control descriptor */ + ATM_VF_HASSAP, /* SAP has been set */ + ATM_VF_CLOSE, /* asynchronous close - treat like VF_RELEASED*/ +}; + #define ATM_VF2VS(flags) \ - ((flags) & ATM_VF_READY ? ATM_VS_CONNECTED : \ - (flags) & ATM_VF_RELEASED ? ATM_VS_CLOSING : \ - (flags) & ATM_VF_LISTEN ? ATM_VS_LISTEN : \ - (flags) & ATM_VF_REGIS ? ATM_VS_INUSE : \ - (flags) & ATM_VF_BOUND ? ATM_VS_BOUND : ATM_VS_IDLE) + (test_bit(ATM_VF_READY,&(flags)) ? ATM_VS_CONNECTED : \ + test_bit(ATM_VF_RELEASED,&(flags)) ? ATM_VS_CLOSING : \ + test_bit(ATM_VF_LISTEN,&(flags)) ? ATM_VS_LISTEN : \ + test_bit(ATM_VF_REGIS,&(flags)) ? ATM_VS_INUSE : \ + test_bit(ATM_VF_BOUND,&(flags)) ? ATM_VS_BOUND : ATM_VS_IDLE) + + +enum { + ATM_DF_CLOSE, /* close device when last VCC is closed */ +}; -#define ATM_DF_CLOSE 1 /* close device when last VCC is closed */ #define ATM_PHY_SIG_LOST 0 /* no carrier/light */ #define ATM_PHY_SIG_UNKNOWN 1 /* carrier/light status is unknown */ @@ -188,8 +257,11 @@ struct atm_cirange { #define ATM_ATMOPT_CLP 1 /* set CLP bit */ +typedef struct { unsigned short bits; } atm_vcc_flags_t; + + struct atm_vcc { - unsigned short flags; /* VCC flags (ATM_VF_*) */ + atm_vcc_flags_t flags; /* VCC flags (ATM_VF_*) */ unsigned char family; /* address family; 0 if unused */ short vpi; /* VPI and VCI (types must be equal */ /* with sockaddr) */ @@ -207,11 +279,12 @@ struct atm_vcc { /* modified by protocol or by driver.*/ /* NOTE: this interface will change */ int (*push_oam)(struct atm_vcc *vcc,void *cell); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); void *dev_data; /* per-device data */ void *proto_data; /* per-protocol data */ struct timeval timestamp; /* AAL timestamps */ struct sk_buff_head recvq; /* receive queue */ - struct atm_aal_stats *stats; /* pointer to AAL stats group */ + struct k_atm_aal_stats *stats; /* pointer to AAL stats group */ wait_queue_head_t sleep; /* if socket is busy */ wait_queue_head_t wsleep; /* if waiting for write buffer space */ struct sock *sk; /* socket backpointer */ @@ -240,6 +313,9 @@ struct atm_dev_addr { }; +typedef struct { unsigned int bits; } atm_dev_flags_t; + + struct atm_dev { const struct atmdev_ops *ops; /* device operations; NULL if unused */ const struct atmphy_ops *phy; /* PHY operations, may be undefined */ @@ -250,11 +326,11 @@ struct atm_dev { struct atm_vcc *last; /* last VCC (or undefined) */ void *dev_data; /* per-device data */ void *phy_data; /* private PHY date */ - unsigned long flags; /* device flags (ATM_DF_*) */ + atm_dev_flags_t flags; /* device flags (ATM_DF_*) */ struct atm_dev_addr *local; /* local ATM addresses */ unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ struct atm_cirange ci_range; /* VPI/VCI range */ - struct atm_dev_stats stats; /* statistics */ + struct k_atm_dev_stats stats; /* statistics */ char signal; /* signal status (ATM_PHY_SIG_*) */ int link_rate; /* link rate (default: OC3) */ #ifdef CONFIG_PROC_FS @@ -307,6 +383,7 @@ struct atmphy_ops { int (*start)(struct atm_dev *dev); int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void *arg); void (*interrupt)(struct atm_dev *dev); + int (*stop)(struct atm_dev *dev); }; struct atm_skb_data { @@ -318,7 +395,7 @@ struct atm_skb_data { #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb)) struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, - int number,unsigned long flags); /* number == -1: pick first available */ + int number,atm_dev_flags_t *flags); /* number == -1: pick first available */ struct atm_dev *atm_find_dev(int number); void atm_dev_deregister(struct atm_dev *dev); void shutdown_atm_dev(struct atm_dev *dev); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 13d09502b2be..bb19b0807c19 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -42,6 +42,9 @@ #define NET_XMIT_DROP 1 /* skb dropped */ #define NET_XMIT_CN 2 /* congestion notification */ #define NET_XMIT_POLICED 3 /* skb is shot by police */ +#define NET_XMIT_BYPASS 4 /* packet does not leave via dequeue; + (TC use only - dev_queue_xmit + returns this as NET_XMIT_SUCCESS) */ #define net_xmit_errno(e) ((e) != NET_XMIT_CN ? -ENOBUFS : 0) diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 8dc90b2e3b85..19f1740f1f3a 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -9,6 +9,7 @@ #ifndef _LINUX_NFS_FS_H #define _LINUX_NFS_FS_H +#include #include #include #include diff --git a/include/linux/sonet.h b/include/linux/sonet.h index c2307389c67a..30c45ec59e2e 100644 --- a/include/linux/sonet.h +++ b/include/linux/sonet.h @@ -1,23 +1,29 @@ /* sonet.h - SONET/SHD physical layer control */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #ifndef LINUX_SONET_H #define LINUX_SONET_H +#define __SONET_ITEMS \ + __HANDLE_ITEM(section_bip); /* section parity errors (B1) */ \ + __HANDLE_ITEM(line_bip); /* line parity errors (B2) */ \ + __HANDLE_ITEM(path_bip); /* path parity errors (B3) */ \ + __HANDLE_ITEM(line_febe); /* line parity errors at remote */ \ + __HANDLE_ITEM(path_febe); /* path parity errors at remote */ \ + __HANDLE_ITEM(corr_hcs); /* correctable header errors */ \ + __HANDLE_ITEM(uncorr_hcs); /* uncorrectable header errors */ \ + __HANDLE_ITEM(tx_cells); /* cells sent */ \ + __HANDLE_ITEM(rx_cells); /* cells received */ + struct sonet_stats { - int section_bip; /* section parity errors (B1) */ - int line_bip; /* line parity errors (B2) */ - int path_bip; /* path parity errors (B3) */ - int line_febe; /* line parity errors at remote */ - int path_febe; /* path parity errors at remote */ - int corr_hcs; /* correctable header errors */ - int uncorr_hcs; /* uncorrectable header errors */ - int tx_cells; /* cells sent */ - int rx_cells; /* cells received */ +#define __HANDLE_ITEM(i) int i + __SONET_ITEMS +#undef __HANDLE_ITEM } __attribute__ ((packed)); + #define SONET_GETSTAT _IOR('a',ATMIOC_PHYTYP,struct sonet_stats) /* get statistics */ #define SONET_GETSTATZ _IOR('a',ATMIOC_PHYTYP+1,struct sonet_stats) @@ -49,4 +55,23 @@ struct sonet_stats { #define SONET_FRSENSE_SIZE 6 /* C1[3],H1[3] (0xff for unknown) */ + +#ifndef __KERNEL__ +#undef __SONET_ITEMS +#else + +#include + +struct k_sonet_stats { +#define __HANDLE_ITEM(i) atomic_t i + __SONET_ITEMS +#undef __HANDLE_ITEM +}; + +extern void sonet_copy_stats(struct k_sonet_stats *from,struct sonet_stats *to); +extern void sonet_subtract_stats(struct k_sonet_stats *from, + struct sonet_stats *to); + +#endif + #endif diff --git a/kernel/exit.c b/kernel/exit.c index 0844e94065e4..c6f22872de4e 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -414,12 +414,12 @@ fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif + task_lock(tsk); sem_exit(); __exit_mm(tsk); __exit_files(tsk); __exit_fs(tsk); __exit_sighand(tsk); - task_lock(tsk); exit_thread(); tsk->state = TASK_ZOMBIE; tsk->exit_code = code; diff --git a/net/atm/Makefile b/net/atm/Makefile index 1c525f6019ef..a43d790b1828 100644 --- a/net/atm/Makefile +++ b/net/atm/Makefile @@ -16,10 +16,6 @@ ifeq ($(CONFIG_ATM),y) O_OBJS = addr.o pvc.o signaling.o svc.o OX_OBJS = common.o atm_misc.o raw.o resources.o -ifeq ($(CONFIG_MMU_HACKS),y) -O_OBJS += mmuio.o -endif - ifeq ($(CONFIG_ATM_CLIP),y) O_OBJS += clip.o NEED_IPCOM = ipcommon.o @@ -36,10 +32,11 @@ OX_OBJS += proc.o endif ifeq ($(CONFIG_ATM_LANE),y) -O_OBJS += lec.o lane_mpoa_init.o +O_OBJS += lec.o +OX_OBJS += lane_mpoa_init.o else ifeq ($(CONFIG_ATM_LANE),m) - O_OBJS += lane_mpoa_init.o + OX_OBJS += lane_mpoa_init.o M_OBJS += lec.o endif endif diff --git a/net/atm/addr.c b/net/atm/addr.c index f7d52a824a5b..8bca9d1c32f6 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -1,11 +1,11 @@ /* net/atm/addr.c - Local ATM address registry */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #include #include -#include +#include #include #include "signaling.h" @@ -41,23 +41,7 @@ static int identical(struct sockaddr_atmsvc *a,struct sockaddr_atmsvc *b) * (which may involve page faults and therefore rescheduling) */ - -static volatile int local_lock = 0; -static wait_queue_head_t local_wait; - - -static void lock_local(void) -{ - while (local_lock) sleep_on(&local_wait); - local_lock = 1; -} - - -static void unlock_local(void) -{ - local_lock = 0; - wake_up(&local_wait); -} +static DECLARE_MUTEX(local_lock); static void notify_sigd(struct atm_dev *dev) @@ -73,13 +57,13 @@ void reset_addr(struct atm_dev *dev) { struct atm_dev_addr *this; - lock_local(); + down(&local_lock); while (dev->local) { this = dev->local; dev->local = this->next; kfree(this); } - unlock_local(); + up(&local_lock); notify_sigd(dev); } @@ -91,20 +75,20 @@ int add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr) error = check_addr(addr); if (error) return error; - lock_local(); + down(&local_lock); for (walk = &dev->local; *walk; walk = &(*walk)->next) if (identical(&(*walk)->addr,addr)) { - unlock_local(); + up(&local_lock); return -EEXIST; } *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_KERNEL); if (!*walk) { - unlock_local(); + up(&local_lock); return -ENOMEM; } (*walk)->addr = *addr; (*walk)->next = NULL; - unlock_local(); + up(&local_lock); notify_sigd(dev); return 0; } @@ -117,17 +101,17 @@ int del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr) error = check_addr(addr); if (error) return error; - lock_local(); + down(&local_lock); for (walk = &dev->local; *walk; walk = &(*walk)->next) if (identical(&(*walk)->addr,addr)) break; if (!*walk) { - unlock_local(); + up(&local_lock); return -ENOENT; } this = *walk; *walk = this->next; kfree(this); - unlock_local(); + up(&local_lock); notify_sigd(dev); return 0; } @@ -138,27 +122,21 @@ int get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size) struct atm_dev_addr *walk; int total; - lock_local(); + down(&local_lock); total = 0; for (walk = dev->local; walk; walk = walk->next) { total += sizeof(struct sockaddr_atmsvc); if (total > size) { - unlock_local(); + up(&local_lock); return -E2BIG; } if (copy_to_user(u_buf,&walk->addr, sizeof(struct sockaddr_atmsvc))) { - unlock_local(); + up(&local_lock); return -EFAULT; } u_buf++; } - unlock_local(); + up(&local_lock); return total; } - - -void init_addr(void) -{ - init_waitqueue_head(&local_wait); -} diff --git a/net/atm/addr.h b/net/atm/addr.h index fcd134023e8c..84a98e7c0e21 100644 --- a/net/atm/addr.h +++ b/net/atm/addr.h @@ -1,6 +1,6 @@ /* net/atm/addr.h - Local ATM address registry */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #ifndef NET_ATM_ADDR_H @@ -14,6 +14,5 @@ void reset_addr(struct atm_dev *dev); int add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size); -void init_addr(void); #endif diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c index 9e2785ed65db..c8e19d2bcc08 100644 --- a/net/atm/atm_misc.c +++ b/net/atm/atm_misc.c @@ -1,12 +1,14 @@ /* net/atm/atm_misc.c - Various functions for use by ATM drivers */ -/* Written 1995-1999 by Werner Almesberger, EPFL ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL ICA */ #include #include #include #include +#include +#include #include #include @@ -16,7 +18,7 @@ int atm_charge(struct atm_vcc *vcc,int truesize) atm_force_charge(vcc,truesize); if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) return 1; atm_return(vcc,truesize); - vcc->stats->rx_drop++; + atomic_inc(&vcc->stats->rx_drop); return 0; } @@ -36,7 +38,7 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, } } atm_return(vcc,guess); - vcc->stats->rx_drop++; + atomic_inc(&vcc->stats->rx_drop); return NULL; } @@ -46,7 +48,7 @@ static int check_ci(struct atm_vcc *vcc,short vpi,int vci) struct atm_vcc *walk; for (walk = vcc->dev->vccs; walk; walk = walk->next) - if ((walk->flags & ATM_VF_ADDR) && walk->vpi == vpi && + if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vpi == vpi && walk->vci == vci && ((walk->qos.txtp.traffic_class != ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) || (walk->qos.rxtp.traffic_class != ATM_NONE && @@ -135,7 +137,25 @@ int atm_pcr_goal(struct atm_trafprm *tp) } +void sonet_copy_stats(struct k_sonet_stats *from,struct sonet_stats *to) +{ +#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) + __SONET_ITEMS +#undef __HANDLE_ITEM +} + + +void sonet_subtract_stats(struct k_sonet_stats *from,struct sonet_stats *to) +{ +#define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i) + __SONET_ITEMS +#undef __HANDLE_ITEM +} + + EXPORT_SYMBOL(atm_charge); EXPORT_SYMBOL(atm_alloc_charge); EXPORT_SYMBOL(atm_find_ci); EXPORT_SYMBOL(atm_pcr_goal); +EXPORT_SYMBOL(sonet_copy_stats); +EXPORT_SYMBOL(sonet_subtract_stats); diff --git a/net/atm/clip.c b/net/atm/clip.c index 98d51c094df0..37610d6d6a0e 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -21,6 +21,7 @@ #include /* for struct sockaddr_in */ #include /* for IFF_UP */ #include +#include #include /* for struct rtable and routing */ #include /* icmp_send */ #include /* for HZ */ @@ -196,6 +197,7 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) atm_return(vcc,skb->truesize); skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs; /* clip_vcc->entry == NULL if we don't have an IP address yet */ + skb->rx_dev = NULL; if (!skb->dev) { kfree_skb(skb); return; @@ -431,7 +433,7 @@ return 0; } clip_priv->stats.tx_packets++; clip_priv->stats.tx_bytes += skb->len; - (void) vcc->dev->ops->send(vcc,skb); + (void) vcc->send(vcc,skb); if (atm_may_send(vcc,0)) { entry->vccs->xoff = 0; return 0; @@ -462,7 +464,6 @@ int clip_mkip(struct atm_vcc *vcc,int timeout) struct clip_vcc *clip_vcc; struct sk_buff_head copy; struct sk_buff *skb; - unsigned long flags; if (!vcc->push) return -EBADFD; clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL); @@ -477,12 +478,9 @@ int clip_mkip(struct atm_vcc *vcc,int timeout) clip_vcc->idle_timeout = timeout*HZ; clip_vcc->old_push = vcc->push; clip_vcc->old_pop = vcc->pop; - save_flags(flags); - cli(); vcc->push = clip_push; vcc->pop = clip_pop; skb_migrate(&vcc->recvq,©); - restore_flags(flags); /* re-process everything received between connection setup and MKIP */ while ((skb = skb_dequeue(©))) if (!clip_devs) { @@ -710,7 +708,7 @@ static struct atm_dev atmarpd_dev = { 999, /* dummy device number */ NULL,NULL, /* pretend not to have any VCCs */ NULL,NULL, /* no data */ - 0, /* no flags */ + { 0 }, /* no flags */ NULL, /* no local address */ { 0 } /* no ESI, no statistics */ }; @@ -729,7 +727,8 @@ int atm_init_atmarp(struct atm_vcc *vcc) add_timer(&idle_timer); } atmarpd = vcc; - vcc->flags |= ATM_VF_READY | ATM_VF_META; + set_bit(ATM_VF_META,&vcc->flags); + set_bit(ATM_VF_READY,&vcc->flags); /* allow replies and avoid getting closed if signaling dies */ bind_vcc(vcc,&atmarpd_dev); vcc->push = NULL; diff --git a/net/atm/common.c b/net/atm/common.c index c4288203c7a6..9625061eb045 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -19,9 +19,11 @@ #include #include /* struct timeval */ #include +#include #include /* struct sock */ #include +#include #include #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) @@ -96,7 +98,7 @@ int atm_create(struct socket *sock,int protocol,int family) if (sock->type == SOCK_STREAM) return -EINVAL; if (!(sk = alloc_atm_vcc_sk(family))) return -ENOMEM; vcc = sk->protinfo.af_atm; - vcc->flags = 0; + memset(&vcc->flags,0,sizeof(vcc->flags)); vcc->dev = NULL; vcc->family = sock->ops->family; vcc->alloc_tx = alloc_tx; @@ -126,7 +128,7 @@ void atm_release_vcc_sk(struct sock *sk,int free_sk) struct sk_buff *skb; vcc = sk->protinfo.af_atm; - vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); if (vcc->dev) { if (vcc->dev->ops->close) vcc->dev->ops->close(vcc); if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */ @@ -156,9 +158,8 @@ int atm_release(struct socket *sock) void atm_async_release_vcc(struct atm_vcc *vcc,int reply) { - vcc->flags |= ATM_VF_CLOSE; + set_bit(ATM_VF_CLOSE,&vcc->flags); vcc->reply = reply; - /*vcc->flags &= ~ATM_VF_READY;*/ wake_up(&vcc->sleep); } @@ -204,6 +205,7 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi, if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; error = 0; + bind_vcc(vcc,dev); switch (vcc->qos.aal) { case ATM_AAL0: error = atm_init_aal0(vcc); @@ -226,8 +228,10 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi, } if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); - if (error) return error; - bind_vcc(vcc,dev); + if (error) { + bind_vcc(vcc,NULL); + return error; + } DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal); DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); @@ -257,8 +261,8 @@ static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci) int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci) { if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC) - vcc->flags &= ~ATM_VF_PARTIAL; - else if (vcc->flags & ATM_VF_PARTIAL) return -EINVAL; + clear_bit(ATM_VF_PARTIAL,&vcc->flags); + else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL; printk(KERN_DEBUG "atm_connect (TX: cl %d,bw %d-%d,sdu %d; " "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, @@ -267,7 +271,7 @@ int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci) vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); - if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; + if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; @@ -285,7 +289,7 @@ int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci) if (!dev) return -ENODEV; } if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) - vcc->flags |= ATM_VF_PARTIAL; + set_bit(ATM_VF_PARTIAL,&vcc->flags); return 0; } @@ -300,7 +304,8 @@ int atm_connect(struct socket *sock,int itf,short vpi,int vci) if (!(vpi || vci)) return -EINVAL; error = atm_connect_vcc(ATM_SD(sock),itf,vpi,vci); if (error) return error; - if (ATM_SD(sock)->flags & ATM_VF_READY) sock->state = SS_CONNECTED; + if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags)) + sock->state = SS_CONNECTED; return 0; } @@ -308,11 +313,10 @@ int atm_connect(struct socket *sock,int itf,short vpi,int vci) int atm_recvmsg(struct socket *sock,struct msghdr *m,int total_len, int flags,struct scm_cookie *scm) { + DECLARE_WAITQUEUE(wait,current); struct atm_vcc *vcc; struct sk_buff *skb; - unsigned long cpu_flags; int eff_len,error; - void *buff; int size; @@ -322,28 +326,33 @@ int atm_recvmsg(struct socket *sock,struct msghdr *m,int total_len, buff = m->msg_iov->iov_base; size = m->msg_iov->iov_len; vcc = ATM_SD(sock); - save_flags(cpu_flags); - cli(); + add_wait_queue(&vcc->sleep,&wait); + set_current_state(TASK_INTERRUPTIBLE); + error = 1; /* <= 0 is error */ while (!(skb = skb_dequeue(&vcc->recvq))) { - if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) { - restore_flags(cpu_flags); - return vcc->reply; + if (test_bit(ATM_VF_RELEASED,&vcc->flags) || + test_bit(ATM_VF_CLOSE,&vcc->flags)) { + error = vcc->reply; + break; } - if (!(vcc->flags & ATM_VF_READY)) { - restore_flags(cpu_flags); - return 0; + if (!test_bit(ATM_VF_READY,&vcc->flags)) { + error = 0; + break; } if (flags & MSG_DONTWAIT) { - restore_flags(cpu_flags); - return -EAGAIN; + error = -EAGAIN; + break; } - interruptible_sleep_on(&vcc->sleep); + schedule(); + set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { - restore_flags(cpu_flags); - return -ERESTARTSYS; + error = -ERESTARTSYS; + break; } } - restore_flags(cpu_flags); + set_current_state(TASK_RUNNING); + remove_wait_queue(&vcc->sleep,&wait); + if (error <= 0) return error; vcc->timestamp = skb->stamp; eff_len = skb->len > size ? size : skb->len; if (vcc->dev->ops->feedback) @@ -383,10 +392,10 @@ int atm_recvmsg(struct socket *sock,struct msghdr *m,int total_len, int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len, struct scm_cookie *scm) { + DECLARE_WAITQUEUE(wait,current); struct atm_vcc *vcc; struct sk_buff *skb; int eff,error; - const void *buff; int size; @@ -396,19 +405,40 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len, buff = m->msg_iov->iov_base; size = m->msg_iov->iov_len; vcc = ATM_SD(sock); - if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) return vcc->reply; - if (!(vcc->flags & ATM_VF_READY)) return -EPIPE; + if (test_bit(ATM_VF_RELEASED,&vcc->flags) || + test_bit(ATM_VF_CLOSE,&vcc->flags)) + return vcc->reply; + if (!test_bit(ATM_VF_READY,&vcc->flags)) return -EPIPE; if (!size) return 0; /* verify_area is done by net/socket.c */ eff = (size+3) & ~3; /* align to word boundary */ + add_wait_queue(&vcc->wsleep,&wait); + set_current_state(TASK_INTERRUPTIBLE); + error = 0; while (!(skb = vcc->alloc_tx(vcc,eff))) { - if (m->msg_flags & MSG_DONTWAIT) return -EAGAIN; - interruptible_sleep_on(&vcc->wsleep); - if (signal_pending(current)) return -ERESTARTSYS; - if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) - return vcc->reply; - if (!(vcc->flags & ATM_VF_READY)) return -EPIPE; + if (m->msg_flags & MSG_DONTWAIT) { + error = -EAGAIN; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + error = -ERESTARTSYS; + break; + } + if (test_bit(ATM_VF_RELEASED,&vcc->flags) || + test_bit(ATM_VF_CLOSE,&vcc->flags)) { + error = vcc->reply; + break; + } + if (!test_bit(ATM_VF_READY,&vcc->flags)) { + error = -EPIPE; + break; + } } + set_current_state(TASK_RUNNING); + remove_wait_queue(&vcc->wsleep,&wait); + if (error) return error; skb->dev = NULL; /* for paths shared with net_device interfaces */ ATM_SKB(skb)->iovcnt = 0; ATM_SKB(skb)->atm_options = vcc->atm_options; @@ -433,7 +463,9 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait) mask = 0; if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq)) mask |= POLLIN | POLLRDNORM; - if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) mask |= POLLHUP; + if (test_bit(ATM_VF_RELEASED,&vcc->flags) || + test_bit(ATM_VF_CLOSE,&vcc->flags)) + mask |= POLLHUP; if (sock->state != SS_CONNECTING) { if (vcc->qos.txtp.traffic_class != ATM_NONE && vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+ @@ -448,20 +480,38 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait) } -static int fetch_stats(struct atm_dev *dev,struct atm_dev_stats *arg,int zero) +static void copy_aal_stats(struct k_atm_aal_stats *from, + struct atm_aal_stats *to) { - unsigned long flags; - int error; +#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) + __AAL_STAT_ITEMS +#undef __HANDLE_ITEM +} - error = 0; - save_flags(flags); - cli(); - if (arg) - error = copy_to_user(arg,&dev->stats, - sizeof(struct atm_dev_stats)); - if (zero && !error) - memset(&dev->stats,0,sizeof(struct atm_dev_stats)); - restore_flags(flags); + +static void subtract_aal_stats(struct k_atm_aal_stats *from, + struct atm_aal_stats *to) +{ +#define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i) + __AAL_STAT_ITEMS +#undef __HANDLE_ITEM +} + + +static int fetch_stats(struct atm_dev *dev,struct atm_dev_stats *arg,int zero) +{ + struct atm_dev_stats tmp; + int error = 0; + + copy_aal_stats(&dev->stats.aal0,&tmp.aal0); + copy_aal_stats(&dev->stats.aal34,&tmp.aal34); + copy_aal_stats(&dev->stats.aal5,&tmp.aal5); + if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); + if (zero && !error) { + subtract_aal_stats(&dev->stats.aal0,&tmp.aal0); + subtract_aal_stats(&dev->stats.aal34,&tmp.aal34); + subtract_aal_stats(&dev->stats.aal5,&tmp.aal5); + } return error ? -EFAULT : 0; } @@ -478,7 +528,8 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) switch (cmd) { case SIOCOUTQ: if (sock->state != SS_CONNECTED || - !(vcc->flags & ATM_VF_READY)) return -EINVAL; + !test_bit(ATM_VF_READY,&vcc->flags)) + return -EINVAL; return put_user(vcc->sk->sndbuf- atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD, (int *) arg) ? -EFAULT : 0; @@ -522,6 +573,14 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) return 0; case ATMSIGD_CTRL: if (!capable(CAP_NET_ADMIN)) return -EPERM; + /* + * The user/kernel protocol for exchanging signalling + * info uses kernel pointers as opaque references, + * so the holder of the file descriptor can scribble + * on the kernel... so we should make sure that we + * have the same privledges that /proc/kcore needs + */ + if (!capable(CAP_SYS_RAWIO)) return -EPERM; error = sigd_attach(vcc); if (!error) sock->state = SS_CONNECTED; return error; @@ -668,6 +727,12 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) write the length" */ return put_user(size, &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0; + case ATM_SETLOOP: + if (__ATM_LM_XTRMT((int) (long) buf) && + __ATM_LM_XTLOC((int) (long) buf) > + __ATM_LM_XTRMT((int) (long) buf)) + return -EINVAL; + /* fall through */ case ATM_SETCIRANGE: case SONET_GETSTATZ: case SONET_SETDIAG: @@ -689,6 +754,14 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) { + /* + * Don't let the QoS change the already connected AAL type nor the + * traffic class. + */ + if (qos->aal != vcc->qos.aal || + qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class || + qos->txtp.traffic_class != vcc->qos.txtp.traffic_class) + return -EINVAL; if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; if (vcc->family == AF_ATMPVC) return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET); @@ -751,7 +824,7 @@ static int atm_do_setsockopt(struct socket *sock,int level,int optname, if (sock->state != SS_UNCONNECTED) return -EBADFD; vcc->qos = qos; - vcc->flags |= ATM_VF_HASQOS; + set_bit(ATM_VF_HASQOS,&vcc->flags); return 0; } case SO_SETCLP: @@ -777,7 +850,8 @@ static int atm_do_getsockopt(struct socket *sock,int level,int optname, vcc = ATM_SD(sock); switch (optname) { case SO_ATMQOS: - if (!(vcc->flags & ATM_VF_HASQOS)) return -EINVAL; + if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) + return -EINVAL; return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ? -EFAULT : 0; case SO_SETCLP: @@ -787,7 +861,8 @@ static int atm_do_getsockopt(struct socket *sock,int level,int optname, { struct sockaddr_atmpvc pvc; - if (!vcc->dev || !(vcc->flags & ATM_VF_ADDR)) + if (!vcc->dev || + !test_bit(ATM_VF_ADDR,&vcc->flags)) return -ENOTCONN; pvc.sap_family = AF_ATMPVC; pvc.sap_addr.itf = vcc->dev->number; diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c index 4bf7a1918b9a..d7c4a4d3a5df 100644 --- a/net/atm/ipcommon.c +++ b/net/atm/ipcommon.c @@ -1,6 +1,6 @@ /* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */ -/* Written 1996,1997 by Werner Almesberger, EPFL LRC */ +/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */ #include @@ -32,20 +32,26 @@ const unsigned char llc_oui[] = { /* * skb_migrate moves the list at FROM to TO, emptying FROM in the process. - * This function should live in skbuff.c or skbuff.h. Note that skb_migrate - * is not atomic, so turn off interrupts when using it. + * This function should live in skbuff.c or skbuff.h. */ void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to) { - struct sk_buff *skb,*prev; + struct sk_buff *skb; + unsigned long flags; - for (skb = ((struct sk_buff *) from)->next; - skb != (struct sk_buff *) from; skb = skb->next) skb->list = to; - prev = from->prev; - from->next->prev = (struct sk_buff *) to; - prev->next = (struct sk_buff *) to; + spin_lock_irqsave(&from->lock,flags); *to = *from; - skb_queue_head_init(from); + from->prev = (struct sk_buff *) from; + from->next = (struct sk_buff *) from; + from->qlen = 0; + spin_unlock_irqrestore(&from->lock,flags); + spin_lock_init(&to->lock); + for (skb = ((struct sk_buff *) to)->next; + skb != (struct sk_buff *) from; skb = skb->next) skb->list = to; + if (to->next == (struct sk_buff *) from) + to->next = (struct sk_buff *) to; + to->next->prev = (struct sk_buff *) to; + to->prev->next = (struct sk_buff *) to; } diff --git a/net/atm/ipcommon.h b/net/atm/ipcommon.h index 105e090d7438..30a5583b053a 100644 --- a/net/atm/ipcommon.h +++ b/net/atm/ipcommon.h @@ -1,6 +1,6 @@ /* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */ -/* Written 1996-1998 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */ #ifndef NET_ATM_IPCOMMON_H @@ -15,6 +15,10 @@ extern struct net_device *clip_devs; +/* + * Moves all skbs from "from" to "to". The operation is atomic for "from", but + * not for "to". "to" may only be accessed after skb_migrate finishes. + */ void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to); diff --git a/net/atm/lane_mpoa_init.c b/net/atm/lane_mpoa_init.c index d1938c187f60..469685703ea2 100644 --- a/net/atm/lane_mpoa_init.c +++ b/net/atm/lane_mpoa_init.c @@ -37,6 +37,18 @@ void atm_mpoa_init(void) #endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +rwlock_t lane_bridge_hook_lock = RW_LOCK_UNLOCKED; +struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, + unsigned char *addr) = NULL; +void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL; +#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) +EXPORT_SYMBOL(lane_bridge_hook_lock); +EXPORT_SYMBOL(br_fdb_get_hook); +EXPORT_SYMBOL(br_fdb_put_hook); +#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */ +#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ + void atm_lane_init(void) { #ifndef CONFIG_ATM_LANE_MODULE /* not module */ diff --git a/net/atm/lec.c b/net/atm/lec.c index 8c6d8d4afff4..701ece763f9b 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -6,6 +6,7 @@ #include #include +#include /* We are ethernet device */ #include @@ -29,9 +30,11 @@ #include #include -/* Bridge */ -#ifdef CONFIG_BRIDGE -#include +/* Proxy LEC knows about bridging */ +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +#include +#include "../bridge/br_private.h" +unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; #endif /* Modular too */ @@ -88,23 +91,19 @@ struct net_device **get_dev_lec (void) { return &dev_lec[0]; } -#ifdef CONFIG_BRIDGE +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) static void handle_bridge(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; char *buff; struct lec_priv *priv; - unsigned char bridge_ula[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; /* Check if this is a BPDU. If so, ask zeppelin to send - * LE_TOPOLOGY_REQUEST with the value of Topology Change bit - * in the Config BPDU*/ + * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit + * as the Config BPDU has */ eth = (struct ethhdr *)skb->data; buff = skb->data + skb->dev->hard_header_len; - if ((memcmp(eth->h_dest, bridge_ula, ETH_ALEN) == 0) && - *buff++ == BRIDGE_LLC1_DSAP && - *buff++ == BRIDGE_LLC1_SSAP && - *buff++ == BRIDGE_LLC1_CTRL) { + if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { struct sk_buff *skb2; struct atmlec_msg *mesg; @@ -113,7 +112,8 @@ static void handle_bridge(struct sk_buff *skb, struct net_device *dev) skb2->len = sizeof(struct atmlec_msg); mesg = (struct atmlec_msg *)skb2->data; mesg->type = l_topology_change; - mesg->content.normal.flag = *(skb->nh.raw + BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) & TOPOLOGY_CHANGE; + buff += 4; + mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */ priv = (struct lec_priv *)dev->priv; atm_force_charge(priv->lecd, skb2->truesize); @@ -123,7 +123,7 @@ static void handle_bridge(struct sk_buff *skb, struct net_device *dev) return; } -#endif /* CONFIG_BRIDGE */ +#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ /* * Modelled after tr_type_trans @@ -219,10 +219,10 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", (long)skb->head, (long)skb->data, (long)skb->tail, (long)skb->end); -#ifdef CONFIG_BRIDGE - if (skb->pkt_bridged == IS_BRIDGED) +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + if (memcmp(skb->data, bridge_ula, sizeof(bridge_ula)) == 0) handle_bridge(skb, dev); -#endif /* CONFIG_BRIDGE */ +#endif /* Make sure we have room for lec_id */ if (skb_headroom(skb) < 2) { @@ -303,7 +303,7 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name, send_vcc, send_vcc?send_vcc->flags:0, entry); - if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) { + if (!send_vcc || !test_bit(ATM_VF_READY,&send_vcc->flags)) { if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { DPRINTK("%s:lec_send_packet: queuing packet, ", dev->name); DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -339,7 +339,7 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) send_vcc->vpi, send_vcc->vci); priv->stats.tx_packets++; priv->stats.tx_bytes += skb2->len; - send_vcc->dev->ops->send(send_vcc, skb2); + send_vcc->send(send_vcc, skb2); } ATM_SKB(skb)->vcc = send_vcc; @@ -348,7 +348,7 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) ATM_SKB(skb)->atm_options = send_vcc->atm_options; priv->stats.tx_packets++; priv->stats.tx_bytes += skb->len; - send_vcc->dev->ops->send(send_vcc, skb); + send_vcc->send(send_vcc, skb); #if 0 /* Should we wait for card's device driver to notify us? */ @@ -463,32 +463,44 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag); break; case l_should_bridge: { -#ifdef CONFIG_BRIDGE - struct fdb *f; - extern Port_data port_info[]; +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + struct net_bridge_fdb_entry *f; DPRINTK("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, mesg->content.proxy.mac_addr[0], mesg->content.proxy.mac_addr[1], mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3], mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]); - f = br_avl_find_addr(mesg->content.proxy.mac_addr); /* bridge/br.c */ + + read_lock(&lane_bridge_hook_lock); + if (br_fdb_get_hook == NULL || dev->br_port == NULL) { + read_unlock(&lane_bridge_hook_lock); + break; + } + + f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr); if (f != NULL && - port_info[f->port].dev != dev && - port_info[f->port].state == Forwarding) { + f->dst->dev != dev && + f->dst->state == BR_STATE_FORWARDING) { /* hit from bridge table, send LE_ARP_RESPONSE */ struct sk_buff *skb2; DPRINTK("%s: entry found, responding to zeppelin\n", dev->name); skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); - if (skb2 == NULL) break; + if (skb2 == NULL) { + br_fdb_put_hook(f); + read_unlock(&lane_bridge_hook_lock); + break; + } skb2->len = sizeof(struct atmlec_msg); memcpy(skb2->data, mesg, sizeof(struct atmlec_msg)); atm_force_charge(priv->lecd, skb2->truesize); skb_queue_tail(&priv->lecd->recvq, skb2); wake_up(&priv->lecd->sleep); } -#endif /* CONFIG_BRIDGE */ + if (f != NULL) br_fdb_put_hook(f); + read_unlock(&lane_bridge_hook_lock); +#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ } break; default: @@ -537,7 +549,7 @@ static struct atm_dev lecatm_dev = { 999, /*dummy device number*/ NULL,NULL, /*no VCCs*/ NULL,NULL, /*no data*/ - 0, /*no flags*/ + { 0 }, /*no flags*/ NULL, /* no local address*/ { 0 } /*no ESI or rest of the atm_dev struct things*/ }; @@ -684,6 +696,7 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) lec_arp_check_empties(priv, vcc, skb); } skb->dev = dev; + skb->rx_dev = NULL; skb->data += 2; /* skip lec_id */ #ifdef CONFIG_TR if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev); @@ -777,7 +790,8 @@ lecd_attach(struct atm_vcc *vcc, int arg) bind_vcc(vcc, &lecatm_dev); vcc->proto_data = dev_lec[i]; - vcc->flags |= ATM_VF_READY | ATM_VF_META; + set_bit(ATM_VF_META,&vcc->flags); + set_bit(ATM_VF_READY,&vcc->flags); /* Set default values to these variables */ priv->maximum_unknown_frame_count = 1; @@ -1055,8 +1069,8 @@ lec_arp_clear_vccs(struct lec_arp_table *entry) if (entry->vcc) { entry->vcc->push = entry->old_push; #if 0 /* August 6, 1998 */ - entry->vcc->flags |= ATM_VF_RELEASED; - entry->vcc->flags &= ~ATM_VF_READY; + set_bit(ATM_VF_RELEASED,&entry->vcc->flags); + clear_bit(ATM_VF_READY,&entry->vcc->flags); entry->vcc->push(entry->vcc, NULL); #endif atm_async_release_vcc(entry->vcc, -EPIPE); @@ -1065,8 +1079,8 @@ lec_arp_clear_vccs(struct lec_arp_table *entry) if (entry->recv_vcc) { entry->recv_vcc->push = entry->old_recv_push; #if 0 - entry->recv_vcc->flags |= ATM_VF_RELEASED; - entry->recv_vcc->flags &= ~ATM_VF_READY; + set_bit(ATM_VF_RELEASED,&entry->vcc->flags); + clear_bit(ATM_VF_READY,&entry->vcc->flags); entry->recv_vcc->push(entry->recv_vcc, NULL); #endif atm_async_release_vcc(entry->recv_vcc, -EPIPE); diff --git a/net/atm/lec.h b/net/atm/lec.h index 4a94c2b6dd8f..dfbf7641663a 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -13,6 +13,14 @@ #include #include +#if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +#include +extern rwlock_t lane_bridge_hook_lock; +struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, + unsigned char *addr); +void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); +#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ + #define LEC_HEADER_LEN 16 struct lecdatahdr_8023 { diff --git a/net/atm/mpc.c b/net/atm/mpc.c index b9247334f5e0..deeb737f5f93 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -2,6 +2,7 @@ #include #include #include +#include /* We are an ethernet device */ #include @@ -522,7 +523,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) atomic_add(skb->truesize, &entry->shortcut->tx_inuse); ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */ ATM_SKB(skb)->atm_options = entry->shortcut->atm_options; - entry->shortcut->dev->ops->send(entry->shortcut, skb); + entry->shortcut->send(entry->shortcut, skb); entry->packets_fwded++; return 0; @@ -739,7 +740,7 @@ static struct atm_dev mpc_dev = { NULL, /* last VCC */ NULL, /* per-device data */ NULL, /* private PHY data */ - 0, /* device flags */ + { 0 }, /* device flags */ NULL, /* local ATM address */ { 0 } /* no ESI */ /* rest of the members will be 0 */ @@ -780,7 +781,8 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) mpc->mpoad_vcc = vcc; bind_vcc(vcc, &mpc_dev); - vcc->flags |= ATM_VF_READY | ATM_VF_META; + set_bit(ATM_VF_META,&vcc->flags); + set_bit(ATM_VF_READY,&vcc->flags); if (mpc->dev) { char empty[ATM_ESA_LEN]; diff --git a/net/atm/proc.c b/net/atm/proc.c index 904dc43ba6a9..79ab6e045c3a 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -33,6 +33,7 @@ #include #include /* for __init */ #include +#include #include /* for HZ */ #include "resources.h" #include "common.h" /* atm_proc_init prototype */ @@ -64,10 +65,12 @@ static struct file_operations proc_spec_atm_operations = { }; static void add_stats(char *buf,const char *aal, - const struct atm_aal_stats *stats) + const struct k_atm_aal_stats *stats) { - sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal,stats->tx, - stats->tx_err,stats->rx,stats->rx_err,stats->rx_drop); + sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal, + atomic_read(&stats->tx),atomic_read(&stats->tx_err), + atomic_read(&stats->rx),atomic_read(&stats->rx_err), + atomic_read(&stats->rx_drop)); } @@ -217,7 +220,7 @@ static void vc_info(struct atm_vcc *vcc,char *buf) default: here += sprintf(here,"%3d",vcc->family); } - here += sprintf(here," %04x %5d %7d/%7d %7d/%7d\n",vcc->flags, + here += sprintf(here," %04x %5d %7d/%7d %7d/%7d\n",vcc->flags.bits, vcc->reply, atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf, atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf); @@ -583,7 +586,7 @@ int __init atm_proc_init(void) struct proc_dir_entry *devices = NULL,*pvc = NULL,*svc = NULL; struct proc_dir_entry *arp = NULL,*lec = NULL,*vc = NULL; - atm_proc_root = proc_mkdir("atm", &proc_root); + atm_proc_root = proc_mkdir("net/atm",NULL); if (!atm_proc_root) return -ENOMEM; CREATE_ENTRY(devices); @@ -605,6 +608,6 @@ cleanup: if (arp) remove_proc_entry("arp",atm_proc_root); if (lec) remove_proc_entry("lec",atm_proc_root); if (vc) remove_proc_entry("vc",atm_proc_root); - remove_proc_entry("atm",&proc_root); + remove_proc_entry("net/atm",NULL); return -ENOMEM; } diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 4b6817eb90f4..2493f04aa6bf 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -1,6 +1,6 @@ /* net/atm/pvc.c - ATM PVC sockets */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #include @@ -13,6 +13,7 @@ #include /* printk */ #include #include +#include #include /* for sock_no_* */ #ifdef CONFIG_ATM_CLIP #include @@ -42,8 +43,8 @@ static int pvc_bind(struct socket *sock,struct sockaddr *sockaddr, addr = (struct sockaddr_atmpvc *) sockaddr; if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT; vcc = ATM_SD(sock); - if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; - if (vcc->flags & ATM_VF_PARTIAL) { + if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; + if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) { if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi; if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci; } @@ -65,7 +66,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, struct sockaddr_atmpvc *addr; struct atm_vcc *vcc = ATM_SD(sock); - if (!vcc->dev || !(vcc->flags & ATM_VF_ADDR)) return -ENOTCONN; + if (!vcc->dev || !test_bit(ATM_VF_ADDR,&vcc->flags)) return -ENOTCONN; *sockaddr_len = sizeof(struct sockaddr_atmpvc); addr = (struct sockaddr_atmpvc *) sockaddr; addr->sap_family = AF_ATMPVC; diff --git a/net/atm/raw.c b/net/atm/raw.c index 355382502492..0899c9f934e1 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c @@ -38,16 +38,34 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) { DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize); atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); wake_up(&vcc->wsleep); } +static int atm_send_aal0(struct atm_vcc *vcc,struct sk_buff *skb) +{ + /* + * Note that if vpi/vci are _ANY or _UNSPEC the below will + * still work + */ + if (!capable(CAP_NET_ADMIN) && + (((u32 *) skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) != + ((vcc->vpi << ATM_HDR_VPI_SHIFT) | (vcc->vci << ATM_HDR_VCI_SHIFT))) + { + kfree_skb(skb); + return -EADDRNOTAVAIL; + } + return vcc->dev->ops->send(vcc,skb); +} + + int atm_init_aal0(struct atm_vcc *vcc) { vcc->push = atm_push_raw; vcc->pop = atm_pop_raw; vcc->push_oam = NULL; + vcc->send = atm_send_aal0; return 0; } @@ -57,6 +75,7 @@ int atm_init_aal34(struct atm_vcc *vcc) vcc->push = atm_push_raw; vcc->pop = atm_pop_raw; vcc->push_oam = NULL; + vcc->send = vcc->dev->ops->send; return 0; } @@ -66,6 +85,7 @@ int atm_init_aal5(struct atm_vcc *vcc) vcc->push = atm_push_raw; vcc->pop = atm_pop_raw; vcc->push_oam = NULL; + vcc->send = vcc->dev->ops->send; return 0; } diff --git a/net/atm/resources.c b/net/atm/resources.c index 116682f5bca1..9502367efa9c 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -1,6 +1,6 @@ /* net/atm/resources.c - Staticly allocated resources */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #include @@ -9,6 +9,7 @@ #include #include /* for barrier */ #include +#include #include /* for struct sock */ #include /* for get_fs_long and put_fs_long */ @@ -66,7 +67,7 @@ struct atm_dev *atm_find_dev(int number) struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, - int number,unsigned long flags) + int number,atm_dev_flags_t *flags) { struct atm_dev *dev; @@ -91,8 +92,9 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, dev->dev_data = NULL; barrier(); dev->ops = ops; - dev->flags = flags; - memset((void *) &dev->stats,0,sizeof(struct atm_dev_stats)); + if (flags) dev->flags = *flags; + else memset(&dev->flags,0,sizeof(dev->flags)); + memset((void *) &dev->stats,0,sizeof(dev->stats)); #ifdef CONFIG_PROC_FS if (ops->proc_read) if (atm_proc_dev_register(dev) < 0) { @@ -118,7 +120,7 @@ void atm_dev_deregister(struct atm_dev *dev) void shutdown_atm_dev(struct atm_dev *dev) { if (dev->vccs) { - dev->flags |= ATM_DF_CLOSE; + set_bit(ATM_DF_CLOSE,&dev->flags); return; } if (dev->ops->dev_close) dev->ops->dev_close(dev); @@ -165,7 +167,7 @@ static void unlink_vcc(struct atm_vcc *vcc,struct atm_dev *hold_dev) if (vcc->next) vcc->next->prev = vcc->prev; else if (vcc->dev) vcc->dev->last = vcc->prev; if (vcc->dev && vcc->dev != hold_dev && !vcc->dev->vccs && - (vcc->dev->flags & ATM_DF_CLOSE)) + test_bit(ATM_DF_CLOSE,&vcc->dev->flags)) shutdown_atm_dev(vcc->dev); } diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 46e22d50c55a..0240aa874c82 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "resources.h" #include "signaling.h" @@ -30,29 +31,33 @@ struct atm_vcc *sigd = NULL; -static wait_queue_head_t sigd_sleep; +static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep); static void sigd_put_skb(struct sk_buff *skb) { #ifdef WAIT_FOR_DEMON static unsigned long silence = 0; -#endif + DECLARE_WAITQUEUE(wait,current); + add_wait_queue(&sigd_sleep,&wait); while (!sigd) { -#ifdef WAIT_FOR_DEMON + set_current_state(TASK_UNINTERRUPTIBLE); if (time_after(jiffies, silence) || silence == 0) { printk(KERN_INFO "atmsvc: waiting for signaling demon " "...\n"); silence = (jiffies+30*HZ)|1; } - sleep_on(&sigd_sleep); + schedule(); + } + remove_wait_queue(&sigd_sleep,&wait); #else + if (!sigd) { printk(KERN_WARNING "atmsvc: no signaling demon\n"); kfree_skb(skb); return; -#endif } +#endif atm_force_charge(sigd,skb->truesize); skb_queue_tail(&sigd->recvq,skb); wake_up(&sigd->sleep); @@ -63,7 +68,8 @@ static void modify_qos(struct atm_vcc *vcc,struct atmsvc_msg *msg) { struct sk_buff *skb; - if ((vcc->flags & ATM_VF_RELEASED) || !(vcc->flags & ATM_VF_READY)) + if (test_bit(ATM_VF_RELEASED,&vcc->flags) || + !test_bit(ATM_VF_READY,&vcc->flags)) return; msg->type = as_error; if (!vcc->dev->ops->change_qos) msg->reply = -EOPNOTSUPP; @@ -114,7 +120,8 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb) session_vcc->qos = msg->qos; break; case as_error: - vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_READY); + clear_bit(ATM_VF_REGIS,&vcc->flags); + clear_bit(ATM_VF_READY,&vcc->flags); vcc->reply = msg->reply; break; case as_indicate: @@ -133,8 +140,8 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb) } return 0; case as_close: - vcc->flags |= ATM_VF_RELEASED; - vcc->flags &= ~ATM_VF_READY; + set_bit(ATM_VF_RELEASED,&vcc->flags); + clear_bit(ATM_VF_READY,&vcc->flags); vcc->reply = msg->reply; break; case as_modify: @@ -177,7 +184,7 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, if (!pvc) memset(&msg->pvc,0,sizeof(msg->pvc)); else msg->pvc = *pvc; sigd_put_skb(skb); - if (vcc) vcc->flags |= ATM_VF_REGIS; + if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags); } @@ -185,8 +192,8 @@ static void purge_vccs(struct atm_vcc *vcc) { while (vcc) { if (vcc->family == PF_ATMSVC && - !(vcc->flags & ATM_VF_META)) { - vcc->flags |= ATM_VF_RELEASED; + !test_bit(ATM_VF_META,&vcc->flags)) { + set_bit(ATM_VF_RELEASED,&vcc->flags); vcc->reply = -EUNATCH; wake_up(&vcc->sleep); } @@ -223,7 +230,7 @@ static struct atm_dev sigd_dev = { 999, /* dummy device number */ NULL,NULL, /* pretend not to have any VCCs */ NULL,NULL, /* no data */ - 0, /* no flags */ + { 0 }, /* no flags */ NULL, /* no local address */ { 0 } /* no ESI, no statistics */ }; @@ -235,13 +242,8 @@ int sigd_attach(struct atm_vcc *vcc) DPRINTK("sigd_attach\n"); sigd = vcc; bind_vcc(vcc,&sigd_dev); - vcc->flags |= ATM_VF_READY | ATM_VF_META; + set_bit(ATM_VF_META,&vcc->flags); + set_bit(ATM_VF_READY,&vcc->flags); wake_up(&sigd_sleep); return 0; } - - -void signaling_init(void) -{ - init_waitqueue_head(&sigd_sleep); -} diff --git a/net/atm/signaling.h b/net/atm/signaling.h index dbb8c21e1504..30d5d51d4d9b 100644 --- a/net/atm/signaling.h +++ b/net/atm/signaling.h @@ -21,6 +21,5 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, const struct sockaddr_atmsvc *svc); int sigd_attach(struct atm_vcc *vcc); -void signaling_init(void); #endif diff --git a/net/atm/svc.c b/net/atm/svc.c index 82ea22072a8c..47b991557dd9 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* for sock_no_* */ #include @@ -59,13 +60,18 @@ static int svc_shutdown(struct socket *sock,int how) static void svc_disconnect(struct atm_vcc *vcc) { + DECLARE_WAITQUEUE(wait,current); struct sk_buff *skb; DPRINTK("svc_disconnect %p\n",vcc); - if (vcc->flags & ATM_VF_REGIS) { + if (test_bit(ATM_VF_REGIS,&vcc->flags)) { sigd_enq(vcc,as_close,NULL,NULL,NULL); - while (!(vcc->flags & ATM_VF_RELEASED) && sigd) - sleep_on(&vcc->sleep); + add_wait_queue(&vcc->sleep,&wait); + while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + remove_wait_queue(&vcc->sleep,&wait); } /* beware - socket is still in use by atmsigd until the last as_indicate has been answered */ @@ -75,8 +81,10 @@ static void svc_disconnect(struct atm_vcc *vcc) the reason */ dev_kfree_skb(skb); } - vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED | ATM_VF_CLOSE); - /* may retry later */ + clear_bit(ATM_VF_REGIS,&vcc->flags); + clear_bit(ATM_VF_RELEASED,&vcc->flags); + clear_bit(ATM_VF_CLOSE,&vcc->flags); + /* ... may retry later */ } @@ -87,7 +95,7 @@ static int svc_release(struct socket *sock) if (!sock->sk) return 0; vcc = ATM_SD(sock); DPRINTK("svc_release %p\n",vcc); - vcc->flags &= ~ATM_VF_READY; + clear_bit(ATM_VF_READY,&vcc->flags); atm_release_vcc_sk(sock->sk,0); svc_disconnect(vcc); /* VCC pointer is used as a reference, so we must not free it @@ -101,6 +109,7 @@ static int svc_release(struct socket *sock) static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, int sockaddr_len) { + DECLARE_WAITQUEUE(wait,current); struct sockaddr_atmsvc *addr; struct atm_vcc *vcc; @@ -108,19 +117,25 @@ static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, if (sock->state == SS_CONNECTED) return -EISCONN; if (sock->state != SS_UNCONNECTED) return -EINVAL; vcc = ATM_SD(sock); - if (vcc->flags & ATM_VF_SESSION) return -EINVAL; + if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; addr = (struct sockaddr_atmsvc *) sockaddr; if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT; - vcc->flags &= ~ATM_VF_BOUND; /* failing rebind will kill old binding */ + clear_bit(ATM_VF_BOUND,&vcc->flags); + /* failing rebind will kill old binding */ /* @@@ check memory (de)allocation on rebind */ - if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; + if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; vcc->local = *addr; vcc->reply = WAITING; sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); - while (vcc->reply == WAITING && sigd) sleep_on(&vcc->sleep); - vcc->flags &= ~ATM_VF_REGIS; /* doesn't count */ + add_wait_queue(&vcc->sleep,&wait); + while (vcc->reply == WAITING && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + remove_wait_queue(&vcc->sleep,&wait); + clear_bit(ATM_VF_REGIS,&vcc->flags); /* doesn't count */ if (!sigd) return -EUNATCH; - if (!vcc->reply) vcc->flags |= ATM_VF_BOUND; + if (!vcc->reply) set_bit(ATM_VF_BOUND,&vcc->flags); return vcc->reply; } @@ -128,6 +143,7 @@ static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, int sockaddr_len,int flags) { + DECLARE_WAITQUEUE(wait,current); struct sockaddr_atmsvc *addr; struct atm_vcc *vcc = ATM_SD(sock); int error; @@ -141,11 +157,13 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, if (vcc->reply) return vcc->reply; } else { + int error; + if (sock->state != SS_UNCONNECTED) return -EINVAL; - if (vcc->flags & ATM_VF_SESSION) return -EINVAL; + if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; addr = (struct sockaddr_atmsvc *) sockaddr; if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT; - if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; + if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; @@ -158,34 +176,46 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, sock->state = SS_CONNECTING; return -EINPROGRESS; } + add_wait_queue(&vcc->sleep,&wait); + error = 0; while (vcc->reply == WAITING && sigd) { - interruptible_sleep_on(&vcc->sleep); - if (signal_pending(current)) { - DPRINTK("*ABORT*\n"); - /* - * This is tricky: - * Kernel ---close--> Demon - * Kernel <--close--- Demon - * or - * Kernel ---close--> Demon - * Kernel <--error--- Demon - * or - * Kernel ---close--> Demon - * Kernel <--okay---- Demon - * Kernel <--close--- Demon - */ - sigd_enq(vcc,as_close,NULL,NULL,NULL); - while (vcc->reply == WAITING && sigd) - sleep_on(&vcc->sleep); - if (!vcc->reply) - while (!(vcc->flags & ATM_VF_RELEASED) - && sigd) sleep_on(&vcc->sleep); - vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED - | ATM_VF_CLOSE); - /* we're gone now but may connect later */ - return -EINTR; + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + if (!signal_pending(current)) continue; + DPRINTK("*ABORT*\n"); + /* + * This is tricky: + * Kernel ---close--> Demon + * Kernel <--close--- Demon + * or + * Kernel ---close--> Demon + * Kernel <--error--- Demon + * or + * Kernel ---close--> Demon + * Kernel <--okay---- Demon + * Kernel <--close--- Demon + */ + sigd_enq(vcc,as_close,NULL,NULL,NULL); + while (vcc->reply == WAITING && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); } + if (!vcc->reply) + while (!test_bit(ATM_VF_RELEASED,&vcc->flags) + && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + remove_wait_queue(&vcc->sleep,&wait); + clear_bit(ATM_VF_REGIS,&vcc->flags); + clear_bit(ATM_VF_RELEASED,&vcc->flags); + clear_bit(ATM_VF_CLOSE,&vcc->flags); + /* we're gone now but may connect later */ + error = -EINTR; + break; } + remove_wait_queue(&vcc->sleep,&wait); + if (error) return error; if (!sigd) return -EUNATCH; if (vcc->reply) return vcc->reply; } @@ -209,16 +239,22 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, static int svc_listen(struct socket *sock,int backlog) { + DECLARE_WAITQUEUE(wait,current); struct atm_vcc *vcc = ATM_SD(sock); DPRINTK("svc_listen %p\n",vcc); /* let server handle listen on unbound sockets */ - if (vcc->flags & ATM_VF_SESSION) return -EINVAL; + if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; vcc->reply = WAITING; sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); - while (vcc->reply == WAITING && sigd) sleep_on(&vcc->sleep); + add_wait_queue(&vcc->sleep,&wait); + while (vcc->reply == WAITING && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + remove_wait_queue(&vcc->sleep,&wait); if (!sigd) return -EUNATCH; - vcc->flags |= ATM_VF_LISTEN; + set_bit(ATM_VF_LISTEN,&vcc->flags); vcc->backlog_quota = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; return vcc->reply; } @@ -240,18 +276,32 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) DPRINTK("svc_accept %p -> %p\n",old_vcc,new_vcc); while (1) { + DECLARE_WAITQUEUE(wait,current); + + add_wait_queue(&old_vcc->sleep,&wait); while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) { - if (old_vcc->flags & ATM_VF_RELEASED) break; - if (old_vcc->flags & ATM_VF_CLOSE) - return old_vcc->reply; - if (flags & O_NONBLOCK) return -EAGAIN; - interruptible_sleep_on(&old_vcc->sleep); - if (signal_pending(current)) return -ERESTARTSYS; + if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break; + if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) { + error = old_vcc->reply; + break; + } + if (flags & O_NONBLOCK) { + error = -EAGAIN; + break; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + if (signal_pending(current)) { + error = -ERESTARTSYS; + break; + } } + remove_wait_queue(&old_vcc->sleep,&wait); + if (error) return error; if (!skb) return -EUNATCH; msg = (struct atmsvc_msg *) skb->data; new_vcc->qos = msg->qos; - new_vcc->flags |= ATM_VF_HASQOS; + set_bit(ATM_VF_HASQOS,&new_vcc->flags); new_vcc->remote = msg->svc; new_vcc->local = msg->local; new_vcc->sap = msg->sap; @@ -267,8 +317,12 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) /* wait should be short, so we ignore the non-blocking flag */ new_vcc->reply = WAITING; sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); - while (new_vcc->reply == WAITING && sigd) - sleep_on(&new_vcc->sleep); + add_wait_queue(&new_vcc->sleep,&wait); + while (new_vcc->reply == WAITING && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + remove_wait_queue(&new_vcc->sleep,&wait); if (!sigd) return -EUNATCH; if (!new_vcc->reply) break; if (new_vcc->reply != -ERESTARTSYS) return new_vcc->reply; @@ -293,6 +347,7 @@ static int svc_getname(struct socket *sock,struct sockaddr *sockaddr, int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) { + DECLARE_WAITQUEUE(wait,current); struct atm_qos save_qos; vcc->reply = WAITING; @@ -300,8 +355,13 @@ int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) vcc->qos = *qos; sigd_enq(vcc,as_modify,NULL,NULL,&vcc->local); vcc->qos = save_qos; - while (vcc->reply == WAITING && !(vcc->flags & ATM_VF_RELEASED) && - sigd) sleep_on(&vcc->sleep); + add_wait_queue(&vcc->sleep,&wait); + while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags) + && sigd) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + remove_wait_queue(&vcc->sleep,&wait); if (!sigd) return -EUNATCH; return vcc->reply; } @@ -317,7 +377,7 @@ static int svc_setsockopt(struct socket *sock,int level,int optname, return atm_setsockopt(sock,level,optname,optval,optlen); vcc = ATM_SD(sock); if (copy_from_user(&vcc->sap,optval,optlen)) return -EFAULT; - vcc->flags |= ATM_VF_HASSAP; + set_bit(ATM_VF_HASSAP,&vcc->flags); return 0; } @@ -393,6 +453,4 @@ void __init atmsvc_proto_init(struct net_proto *pro) printk(KERN_ERR "ATMSVC: can't register"); return; } - signaling_init(); - init_addr(); } diff --git a/net/bridge/br.c b/net/bridge/br.c index ec59ff6220e4..2c3d08df6069 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br.c,v 1.39 2000/02/18 16:47:11 davem Exp $ + * $Id: br.c,v 1.40 2000/03/21 21:08:47 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,6 +23,10 @@ #include #include "br_private.h" +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +#include "../atm/lec.h" +#endif + void br_dec_use_count() { MOD_DEC_USE_COUNT; @@ -39,6 +43,12 @@ static int __init br_init(void) br_handle_frame_hook = br_handle_frame; br_ioctl_hook = br_ioctl_deviceless_stub; +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + write_lock(&lane_bridge_hook_lock); + br_fdb_get_hook = br_fdb_get; + br_fdb_put_hook = br_fdb_put; + write_unlock(&lane_bridge_hook_lock); +#endif register_netdevice_notifier(&br_device_notifier); return 0; @@ -59,6 +69,12 @@ static void __exit br_deinit(void) unregister_netdevice_notifier(&br_device_notifier); br_call_ioctl_atomic(__br_clear_ioctl_hook); net_call_rx_atomic(__br_clear_frame_hook); +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + write_lock(&lane_bridge_hook_lock); + br_fdb_get_hook = NULL; + br_fdb_put_hook = NULL; + write_unlock(&lane_bridge_hook_lock); +#endif } EXPORT_NO_SYMBOLS; diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e6fa6b379d07..fc549d76a899 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_input.c,v 1.3 2000/02/24 19:48:06 davem Exp $ + * $Id: br_input.c,v 1.4 2000/03/21 21:08:47 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,7 +19,7 @@ #include #include "br_private.h" -unsigned char bridge_ula[5] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; +unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) { @@ -53,6 +53,8 @@ static void __br_handle_frame(struct sk_buff *skb) p->state == BR_STATE_DISABLED) goto freeandout; + skb_push(skb, skb->data - skb->mac.raw); + if (br->dev.flags & IFF_PROMISC) { struct sk_buff *skb2; @@ -81,8 +83,6 @@ static void __br_handle_frame(struct sk_buff *skb) if (!memcmp(dest, bridge_ula, 5) && !(dest[5] & 0xF0)) goto handle_special_frame; - skb_push(skb, skb->data - skb->mac.raw); - if (p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING) br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 084e81b4b0e3..76c14be9ccf0 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -4,7 +4,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_private.h,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_private.h,v 1.2 2000/03/21 21:08:47 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -114,7 +114,7 @@ struct net_bridge }; struct notifier_block br_device_notifier; -unsigned char bridge_ula[5]; +unsigned char bridge_ula[6]; /* br.c */ void br_dec_use_count(void); diff --git a/net/core/dev.c b/net/core/dev.c index b09b3b9a472e..f14753618998 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -651,7 +651,7 @@ int dev_queue_xmit(struct sk_buff *skb) qdisc_run(dev); spin_unlock_bh(&dev->queue_lock); - return ret; + return ret == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : ret; } /* The device has no queue. Common case for software devices: diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 2823c2c7e683..c3f3b29f765d 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -1,7 +1,7 @@ /* * Linux NET3: IP/IP protocol decoder. * - * Version: $Id: ipip.c,v 1.31 2000/03/17 14:41:51 davem Exp $ + * Version: $Id: ipip.c,v 1.32 2000/03/21 06:13:54 davem Exp $ * * Authors: * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index d5ca01aa6f30..5325383218aa 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -491,7 +491,7 @@ netlink_send_peer(ipq_queue_element_t *e) skb = netlink_build_message(e, &status); if (skb == NULL) return status; - return netlink_unicast(nfnl, skb, nlq->peer.pid, 0); + return netlink_unicast(nfnl, skb, nlq->peer.pid, MSG_DONTWAIT); } static struct sk_buff * diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 091a9eb06893..575ec303693b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.189 2000/02/27 19:52:55 davem Exp $ + * Version: $Id: tcp_input.c,v 1.190 2000/03/21 19:34:23 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1edee9f51bb8..b6eef93a54ec 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2015,7 +2015,7 @@ static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i) timer_expires = jiffies; sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p %u %u %u %u", + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u", i, src, srcp, dest, destp, sp->state, tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq, timer_active, timer_expires-jiffies, diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index c52797d70a13..8b8db60d8feb 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -6,7 +6,7 @@ * Pedro Roque * Alexey Kuznetsov * - * $Id: sit.c,v 1.36 2000/03/17 14:42:08 davem Exp $ + * $Id: sit.c,v 1.37 2000/03/21 06:14:00 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index a3b25f2a78ee..021d7d658ca9 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -276,7 +276,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, goto err_out; } /* @@@ should check if the socket is really operational or we'll crash - on vcc->dev->ops->send */ + on vcc->send */ if (classid) { if (TC_H_MAJ(classid ^ sch->handle)) { DPRINTK("atm_tc_change: classid mismatch\n"); @@ -449,8 +449,21 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) sch->stats.packets++; flow->stats.bytes += skb->len; flow->stats.packets++; - sch->q.qlen++; - return 0; + /* + * Okay, this may seem weird. We pretend we've dropped the packet if + * it goes via ATM. The reason for this is that the outer qdisc + * expects to be able to q->dequeue the packet later on if we return + * success at this place. Also, sch->q.qdisc needs to reflect whether + * there is a packet egligible for dequeuing or not. Note that the + * statistics of the outer qdisc are necessarily wrong because of all + * this. There's currently no correct solution for this. + */ + if (flow == &p->link) { + sch->q.qlen++; + return 0; + } + tasklet_schedule(&p->task); + return NET_XMIT_BYPASS; } @@ -477,11 +490,9 @@ static void sch_atm_dequeue(unsigned long data) */ while ((skb = flow->q->dequeue(flow->q))) { if (!atm_may_send(flow->vcc,skb->truesize)) { - if (flow->q->ops->requeue(skb,flow->q)) - sch->q.qlen--; + (void) flow->q->ops->requeue(skb,flow->q); break; } - sch->q.qlen--; D2PRINTK("atm_tc_deqeueue: sending on class %p\n",flow); /* remove any LL header somebody else has attached */ skb_pull(skb,(char *) skb->nh.iph-(char *) skb->data); @@ -501,7 +512,7 @@ static void sch_atm_dequeue(unsigned long data) atomic_add(skb->truesize,&flow->vcc->tx_inuse); ATM_SKB(skb)->iovcnt = 0; /* atm.atm_options are already set by atm_tc_enqueue */ - (void) flow->vcc->dev->ops->send(flow->vcc,skb); + (void) flow->vcc->send(flow->vcc,skb); } } -- 2.39.5