]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.99pre3-6 2.3.99pre3-6
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:33:25 +0000 (15:33 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:33:25 +0000 (15:33 -0500)
95 files changed:
CREDITS
Documentation/Configure.help
MAINTAINERS
Makefile
arch/sparc/Makefile
arch/sparc64/Makefile
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/sys_sparc32.c
drivers/atm/Makefile
drivers/atm/ambassador.c
drivers/atm/ambassador.h
drivers/atm/atmdev_init.c
drivers/atm/atmtcp.c
drivers/atm/eni.c
drivers/atm/eni.h
drivers/atm/fore200e.c
drivers/atm/fore200e.h
drivers/atm/horizon.c
drivers/atm/horizon.h
drivers/atm/idt77105.c
drivers/atm/iphase.c
drivers/atm/nicstar.c
drivers/atm/nicstar.h
drivers/atm/suni.c
drivers/atm/suni.h
drivers/atm/uPD98402.c
drivers/atm/zatm.c
drivers/char/atixlmouse.c
drivers/char/busmouse.c
drivers/char/busmouse.h
drivers/char/misc.c
drivers/ieee1394/Config.in
drivers/ieee1394/csr.c
drivers/ieee1394/csr.h
drivers/ieee1394/highlevel.c
drivers/ieee1394/highlevel.h
drivers/ieee1394/ieee1394.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_types.h
drivers/ieee1394/ohci1394.c
drivers/ieee1394/ohci1394.h
drivers/ieee1394/pcilynx.c
drivers/ieee1394/pcilynx.h
drivers/ieee1394/raw1394.c
drivers/ieee1394/raw1394.h
drivers/sbus/char/sunmouse.c
drivers/sbus/char/sunserial.c
drivers/scsi/qlogicisp.c
drivers/sound/sb_card.c.rej [deleted file]
drivers/video/cgthreefb.c
fs/nfs/flushd.c
fs/nfs/write.c
fs/pipe.c
include/asm-sparc/asm_offsets.h
include/asm-sparc/pgtable.h
include/asm-sparc64/page.h
include/linux/atm_idt77105.h
include/linux/atm_suni.h
include/linux/atmdev.h
include/linux/netdevice.h
include/linux/nfs_fs.h
include/linux/sonet.h
kernel/exit.c
net/atm/Makefile
net/atm/addr.c
net/atm/addr.h
net/atm/atm_misc.c
net/atm/clip.c
net/atm/common.c
net/atm/ipcommon.c
net/atm/ipcommon.h
net/atm/lane_mpoa_init.c
net/atm/lec.c
net/atm/lec.h
net/atm/mpc.c
net/atm/proc.c
net/atm/pvc.c
net/atm/raw.c
net/atm/resources.c
net/atm/signaling.c
net/atm/signaling.h
net/atm/svc.c
net/bridge/br.c
net/bridge/br_input.c
net/bridge/br_private.h
net/core/dev.c
net/ipv4/ipip.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv6/sit.c
net/sched/sch_atm.c

diff --git a/CREDITS b/CREDITS
index 4fa4ef90bf4d71b363d03a2c5ca7f687bf6cfc74..fe323fbfbc8c8ac260d893312dac121b6e2bf3a2 100644 (file)
--- 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/
index bcf2d831ec2f896af9bea197c2e51400aa997018..ec5703e89c070339728882038bb65292ff5c1690 100644 (file)
@@ -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 <quango@themall.net> et al.
index f03fbb625c9e0d818206c5f64643e24054f0027c..2a5276f5196e8e9c1666aec194ebbb1707896163 100644 (file)
@@ -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
index 8e6a0f0efe642da3e1ddf56c94bbe452e48972ce..184c30b82c2cbf2bdf4b3795b51340cc6b7ccb2f 100644 (file)
--- 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
index 6725e8cfe12d992d2c4e30103685a578fc5705ab..2fe7a2c1854f8ab74b563cce1f1539b63bd91916 100644 (file)
@@ -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
index 868dd685152cb459316efc01f817edcb6b7b9480..585fa4a3b5515012dbc0828c098e152211ce00e3 100644 (file)
@@ -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
index f06ece6823e73a78c33f0d4a40dc19614bde5003..124776f51f4e1ecce5d4b609be2001266e89c89f 100644 (file)
@@ -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
index 0ba88adf66a6fa0455c50144576d6c2e089d5c97..92aa5f6ad638034e30ec0864ad30b9bb4b31b525 100644 (file)
@@ -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)
index 763acdc0f1ab25cd2d0978a2c5fcdd7f5db105b3..58b8d3c2bf90132a526ddce5d19e42f3576ef16a 100644 (file)
@@ -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);
index f126bd232717bb7f5329ce287afabbf96d4b4139..8dbf1364aa73ba85d05f88e3223a41326348cb48 100644 (file)
@@ -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
index 8ec9960c15ccb97ad41e77858b4522ce07865afc..a71884db7d8921b71af0078b62a437381af11831 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
+#include <asm/atomic.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -39,7 +40,7 @@
 
 #define maintainer_string "Giuliano Procida at Madge Networks <gprocida@madge.com>"
 #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
index 93e458644463e9d1dea2f75601ba944f6c843ad5..11ce866dab48a0409cffd2e367f5b57f27689bbf 100644 (file)
 #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 {
index 357cbdbe0120563f0885205c4ac3d88144411f93..443831a82b8aa100b6fd17e48d139f7e8ecda94b 100644 (file)
@@ -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();
index cc13eb06f50f927f074f1c1d11437c2ed0aa0bc7..64c25420eb3bfacb070ec42ab279646711760ca3 100644 (file)
@@ -7,7 +7,9 @@
 #include <linux/wait.h>
 #include <linux/atmdev.h>
 #include <linux/atm_tcp.h>
+#include <linux/bitops.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 
 
 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;
index 081fcdfed28db871cc697f8c9d12036fc39430bd..b3240d498957157d94de7b9f3aaad4cce6a9d521 100644 (file)
 #include <linux/uio.h>
 #include <linux/init.h>
 #include <linux/atm_eni.h>
+#include <linux/bitops.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
@@ -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);
index 76d0dd482fe2c0012b142bd34fc2c2b286df181a..23ba60fb1e9e1bb8aeb8d0e26c72de6b88dd42a0 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/skbuff.h>
 #include <linux/time.h>
 #include <linux/pci.h>
+#include <linux/spinlock.h>
 
 #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 */
index 4c07f2e7f164441ed1b654c518eab58d6121389f..96c0228427035d264a5671589300e91b0c175a1f 100644 (file)
@@ -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 <linux/atmdev.h>
 #include <linux/sonet.h>
 #include <linux/atm_suni.h>
+#include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/string.h>
 #include <asm/segment.h>
@@ -43,6 +44,7 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 
 #ifdef CONFIG_ATM_FORE200E_PCA
 #include <linux/pci.h>
@@ -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--) {
index eea20162bca6931c67a93a06bb6c261dad3c8625..fb7d92259631c78743011e6ed4f42e9c249651b6 100644 (file)
@@ -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 {
index 0a412667e2a720ae70b7df2c17e228e1aa69ee3a..f0dff701117bfb72e1dc586c5b7a15a7f87d4778 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
@@ -50,7 +51,7 @@
 
 #define maintainer_string "Giuliano Procida at Madge Networks <gprocida@madge.com>"
 #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<<CR_MAXPEXP) {
       PRINTD (DBG_QOS, "set_cr internal failure: d=%u p=%u",
@@ -813,7 +814,7 @@ static inline void hrz_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);
   }
 }
 
@@ -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 {
index be5e5c726c2837e9cde30f59b8da75f79e094d1f..6655bdc1cf96a122a91040399fdc5ef12ebfc328 100644 (file)
 #define DRIVER_ATM_HORIZON_H
 
 #include <linux/config.h>
-
 #include <linux/version.h>
 
-
 #ifdef CONFIG_ATM_HORIZON_DEBUG
 #define DEBUG_HORIZON
 #endif
index 3d305858aa22e67ee7a5313ee120b0376d30d248..31503ed1e6b75c993f2a33cba24de30d598c65d3 100644 (file)
@@ -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;
         }
         
index 84bdda6d660ec119892420fdf037fed2fc2a124b..cd1714a53b09e6de684c88c5ded09cf32c6f5ca4 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/init.h>  
 #include <asm/system.h>  
 #include <asm/io.h>  
+#include <asm/atomic.h>  
 #include <asm/uaccess.h>  
 #include <asm/string.h>  
 #include <asm/byteorder.h>  
@@ -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 = &regs_local.ffredn;
              rfredn_t        *rfL = &regs_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*)&regs_local,sizeof(ia_regs_t));
+             if (copy_to_user(ia_cmds.buf, &regs_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);)  
index 3e4930fdd1382021ad5ac1e852614bb5e71898f3..767fd75fb9d7efa424ba810281943c032faa87e4 100644 (file)
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 #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)
index 61b89efe0f4cd5cc5d124dafd5824dee7ab66c69..4e90650c01dd29bc529a01ffb6be5c06907460e8 100644 (file)
 
 #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 */
 
index 7335bbb32f9fca6ca6517d1353c8e52e005dec7a..0de6e8eadcf81d4ccd1653374646a30dfabc4aad 100644 (file)
@@ -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 <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 
 #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,
 };
 
 
index f72cdc7beebbf82c9425d1913946c0d265f6868b..ae6d39abbddf1bef2f34ae1e9d6bf7273b896e06 100644 (file)
@@ -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
index 36fd70b170e467b96ffbb1f56aa2f8e9f26d457b..7c5f5757935dc0e7b92d7caa9825cdc0c1b16c24 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/sonet.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 
 #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,
 };
 
 
index 26c8c9d90b0d89b2d10cd5a2c4864ccdc12d14bb..1b68f552996927607b288bb86a357c974048a7ea 100644 (file)
 #include <linux/init.h>
 #include <linux/atm_zatm.h>
 #include <linux/capability.h>
+#include <linux/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
+#include <asm/atomic.h>
 #include <asm/uaccess.h>
 
 #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;
index 4c4b6ccf95b65e77c3207dfab57ac590f467b783..4bc4b64ff00f6dd474d400291099d76cfedea2cc 100644 (file)
@@ -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 */
index f2314a2f7e6958e39c8f5fb77583d2e8a80d8c56..04ff370f35a689d0426ebd1d4a125a0746aafb08 100644 (file)
@@ -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
index 3626334d945fa541cb2603f976504d41e0ed4a05..4ba7c9ce4a88295166657c69f15991e34a15c335 100644 (file)
@@ -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
index 870cb50fb7b572ea471f1ab9d47093697b3dce33..7cb29f93629a1a1ecf68ae622ef54baa164b4766 100644 (file)
@@ -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
index 899add4900dafdabf6cc7a193216d41e0f269374..df0e3cfd2058bfe9f356a002f21f2235103b59d5 100644 (file)
@@ -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
index 4ffe0faddbc5f5e5786e3bb5f8f9a1678216aeed..a884f2a1c27c60e8705f3dfd3fe26023b254b7cd 100644 (file)
@@ -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,
 };
 
 
index 70bacdd10e0faa6b541b9b8be893f675476c3262..7bc97f549d6684bc7e1c1a1c716efd29de971103 100644 (file)
@@ -46,7 +46,6 @@ struct csr_control {
 
         quadlet_t topology_map[256];
         quadlet_t speed_map[1024];
-        quadlet_t fcp_data[1024];
 };
 
 
index 3b4ac40f5475079492888759afb40cdacf71b6a9..3e20824aa99a4941d612590368a127c9d0f92aa0 100644 (file)
@@ -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;
                         }
index 9bf40674295abd3187d8bf7d36dbbd6d81565d5a..f4f615a7b2c066d4972ae773c4a28c9a3ce7b57c 100644 (file)
@@ -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);
 
 
 /*
index dfca3aef303c3ae8ffde832453ea57f52d0c4110..c9f42373e3274b6338d3c859e0a4c9250381a1ff 100644 (file)
 #define SELFID_PORT_NCONN        0x1
 #define SELFID_PORT_NONE         0x0   
 
+
+#include <asm/byteorder.h>
+
+#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 */
index 771189f0b37e3111592879007226f2d3a4cf0840..c7ce7314437af29a6ab3eeecab76b65d983e8dca 100644 (file)
@@ -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 <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
@@ -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;
 
index 171a2fa9fe84387b095b95c7be679ea45175bd0d..636aef40e958a575971efdca0ad953c99aa6d0af 100644 (file)
@@ -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);
index e2eeffc682da8d2881c8277a115fe60f417efd97..6f07a7f6a2e9b49590e3032c6bf4e12510eaae13 100644 (file)
@@ -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:
index d619182dd87b6a17072cb6c0e3caef0ddc22fd9f..d817e61c6a95496f99f3f4096ddab1a01502d105 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/version.h>
 #include <linux/list.h>
+#include <asm/byteorder.h>
 
 
 #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)
index b8fae7ee274e2ccb5e962d15399152841e505683..488e013fbb5c3a79f5d81377525eca3d6f76b3ed 100644 (file)
  * . 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        <emilie.chung@axis.com>
+ *  .Tip on Async Request Filter
+ * Pascal Drolet <pascal.drolet@informission.ca>
+ *  .Various tips for optimization and functionnalities
  */
 
 #include <linux/config.h>
 #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;i<ohci->nb_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 <emilie.chung@axis.com>)
         */
        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 <pascal.drolet@informission.ca>
+ */
+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;i<sizeof(ohci_csr_rom)/4;i++)
+               ohci->csr_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);
index 46d9a270fd2d11a937e6c5d17b218d133982f201..f0ec83d48021f5e2034981a07e0cc9f873179057 100644 (file)
@@ -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
 #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;
index 2714a6eb5aca2ae04079d6369eb8c8084ebd1ab7..773d68983431fb79017502a40bdf3f2375b0d109 100644 (file)
 /* 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;
index 2809bde0832138615550a97dc4e3c145b922664f..a65182045f4519b5a622aec9e3479c5b5b4a61a2 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 
 #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 _
index 0e63acb33134147d6bd078ec5e3a6a0ab11bb0f3..4a994aba5a4c91a6ba1381d5cba8ec3e686a9082 100644 (file)
@@ -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 = {
index b1b0e4b90586ec8cf746cc6765ee593908e656fe..f23bfc0512a0141fd5af4c952698b50bd22236ab 100644 (file)
@@ -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
 #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;
index 091702d156ac045f866330f773157cf86e2bdb7d..f1641a33a51b1c427d7dd472589a1937fb1e414c 100644 (file)
@@ -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;
 }
index 9719f625a217f2e9c7e0a903df8c23ea0a62cc6b..e58eb1ef7800678e631564a2f1e55b0452c9fa9b 100644 (file)
@@ -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);
index 190a4bcb989015f43d37e8a4e601cc424609cfd0..8e9c314baa72f7b8486f291049a5b7cd2674e4af 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/blk.h>
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/sound/sb_card.c.rej b/drivers/sound/sb_card.c.rej
deleted file mode 100644 (file)
index 981347f..0000000
+++ /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 <twerner@intercomm.de>\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 <azummo@ita.flashnet.it>\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 <twerner@intercomm.de>\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 <twerner@intercomm.de>\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. */
-  
index 5e4d45a9ebfa2aa41c57512170dff6eeac7d22dc..9cec20abfa4f31edfbcc8caf69e54338da0afa7e 100644 (file)
@@ -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);
 }
 
index 66476bca660fed4d6b8298bb443729f1afbf027e..d36c3a9aecee596d54b8b4ee12ab78801bd4f26e 100644 (file)
@@ -22,6 +22,7 @@
  * Copyright (C) 1999, 2000, Trond Myklebust <trond.myklebust@fys.uio.no>
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
 #include <linux/pagemap.h>
index d7dec8fed234a13e31a7ef929f5805237e8ccb64..96dfebe6835bb0e94f6dd4200d454c2aa0d15bef 100644 (file)
@@ -46,6 +46,7 @@
  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
 #include <linux/swap.h>
index 653110847a46ee3c8265256b3defd4bef0103852..f25f5e514a1f137a7e6dc0515298099a5b7de0d8 100644 (file)
--- 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;
index 3bbf39b20942c74c2080424574a36ecec1663e8a..57c2ffd9bd0775b1915ea436ffe24c15d4fbc7fe 100644 (file)
 #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
 #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
index b0543fffb870008405f198665b822a38fae4442a..8925923b0de363e1de3554cc2e3c6f2ed5b69529 100644 (file)
@@ -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)
index 757f43c4ddbe630cbd6ca91de2d88ba3141be24c..7211c7d81846d18a9bc1fa5e18c2388db73660d4 100644 (file)
@@ -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
index 70e9e6e590aef35353d07930e81b280f2bfc8ae5..05621cf20709cdfee1fae5ad785275a32419f74c 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <asm/types.h>
 #include <linux/atmioc.h>
+#include <linux/atmdev.h>
 
 /*
  * 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
index 2e6a01a6180552c6429f94c3c4922fe7dd15de13..84f3aab54468dfd0101ea80cea22ae0e56d73b13 100644 (file)
@@ -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 <linux/atmioc.h>
-
-#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
index 95e97de35f32b1723467fd34bea52a6a67317655..0a9eb9762f5f194f4dc207bd2341e91909ae087f 100644 (file)
@@ -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 */
 #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 <linux/sched.h> /* wait_queue_head_t */
 #include <linux/time.h> /* 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);
index 13d09502b2be17063d81479eb2e36ee4f1242b30..bb19b0807c193b25298ff977cfe282d74a24e64f 100644 (file)
@@ -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)
 
index 8dc90b2e3b854c3b0da2298508b5aa7fdd049594..19f1740f1f3a8f4d5fdd9737a1ba2d12b5fd7f26 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _LINUX_NFS_FS_H
 #define _LINUX_NFS_FS_H
 
+#include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/pagemap.h>
index c2307389c67a05709a8149787e56bc5fc578037c..30c45ec59e2ebd3657d88b2c0cf250170da83deb 100644 (file)
@@ -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 <asm/atomic.h>
+
+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
index 0844e94065e4e4f7978ac6a0ce95813e5785bd48..c6f22872de4e33ecb00d2e81b3091fb8fd1314e1 100644 (file)
@@ -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;
index 1c525f6019ef157ac3477cc127b0cc6a60a48c27..a43d790b1828d80c404874de1a5e221f1f92efef 100644 (file)
@@ -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
index f7d52a824a5bb6cad7bfee4e31b6130d7e66ee81..8bca9d1c32f6d3451515d404b958f4acdcc909bf 100644 (file)
@@ -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 <linux/atm.h>
 #include <linux/atmdev.h>
-#include <linux/wait.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 #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);
-}
index fcd134023e8ca6b25641c3d65c7fea65e711b28a..84a98e7c0e21245c91e0f60c73bbb63012e2d75a 100644 (file)
@@ -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
index 9e2785ed65db7ffc7930c84b5f725c8ff3c545e8..c8e19d2bcc082bd87c2cd0b4e67f3e5cfb90d765 100644 (file)
@@ -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 <linux/module.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
 #include <linux/skbuff.h>
+#include <linux/sonet.h>
+#include <linux/bitops.h>
 #include <asm/atomic.h>
 #include <asm/errno.h>
 
@@ -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);
index 98d51c094df04679e509cbc6627b7f28a8dea99c..37610d6d6a0efb32974de9d777237e3d9c64eaf0 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/in.h> /* for struct sockaddr_in */
 #include <linux/if.h> /* for IFF_UP */
 #include <linux/inetdevice.h>
+#include <linux/bitops.h>
 #include <net/route.h> /* for struct rtable and routing */
 #include <net/icmp.h> /* icmp_send */
 #include <asm/param.h> /* 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,&copy);
-       restore_flags(flags);
        /* re-process everything received between connection setup and MKIP */
        while ((skb = skb_dequeue(&copy)))
                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;
index c4288203c7a6f3c2221fc5911b420b4b78700e2b..9625061eb045186b0d960d51240a8e0f928e90b3 100644 (file)
 #include <linux/sched.h>
 #include <linux/time.h>                /* struct timeval */
 #include <linux/skbuff.h>
+#include <linux/bitops.h>
 #include <net/sock.h>          /* struct sock */
 
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 #include <asm/poll.h>
 
 #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;
index 4bf7a1918b9a3d12dc83400f996f598c477218cf..d7c4a4d3a5df35596e9d37637b21bdb9d9641ce8 100644 (file)
@@ -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 <linux/string.h>
@@ -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;
 }
index 105e090d74380e43dac63fb79640b77d35032cd0..30a5583b053afefcc5947dbf7908c96d51e3ea75 100644 (file)
@@ -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
 
 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);
 
index d1938c187f607621852bc6a47010c1ed2df50551..469685703ea22f3429a29ca0b8c57e6124e19b2e 100644 (file)
@@ -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 */
index 8c6d8d4afff43c6ccf23b97226361d484e3de68b..701ece763f9bdee104a17ac73c6fff0dfd7280e2 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/bitops.h>
 
 /* We are ethernet device */
 #include <linux/if_ether.h>
 #include <linux/atmdev.h>
 #include <linux/atmlec.h>
 
-/* Bridge */
-#ifdef CONFIG_BRIDGE
-#include <net/br.h>
+/* Proxy LEC knows about bridging */
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
+#include <linux/if_bridge.h>
+#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);
index 4a94c2b6dd8f951d56fb4559a6ef3efcde53a9c1..dfbf7641663a47ca82fd7277f97a52400113aafa 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/atmlec.h>
 
+#if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
+#include <linux/if_bridge.h>
+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 {
index b9247334f5e0515d0e50a23f30a01ec4282bcb4d..deeb737f5f93bb2115e7cd146ebd75064dcdede5 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/bitops.h>
 
 /* We are an ethernet device */
 #include <linux/if_ether.h>
@@ -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];
index 904dc43ba6a97d8ad9fd8f1d62338aa31015ab8f..79ab6e045c3ad04e81d3db03aed85bd908df5ae0 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/if_arp.h>
 #include <linux/init.h> /* for __init */
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 #include <asm/param.h> /* 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;
 }
index 4b6817eb90f4b9d4882e785dc431056f037816b2..2493f04aa6bfbf6526cfdc73dbaaaa4a191bfd4b 100644 (file)
@@ -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 <linux/config.h>
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>      /* printk */
 #include <linux/init.h>
 #include <linux/skbuff.h>
+#include <linux/bitops.h>
 #include <net/sock.h>          /* for sock_no_* */
 #ifdef CONFIG_ATM_CLIP
 #include <net/atmclip.h>
@@ -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;
index 355382502492d79a3bd66f0d482cf5e8a89e37e4..0899c9f934e12b2c75e07bd741179d345029cfe9 100644 (file)
@@ -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;
 }
 
index 116682f5bca1a4f8cbdae3dd330e9f3a747ea70e..9502367efa9c661d908aeaf636c6fd7218310588 100644 (file)
@@ -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 <linux/config.h>
@@ -9,6 +9,7 @@
 #include <linux/atmdev.h>
 #include <linux/kernel.h> /* for barrier */
 #include <linux/module.h>
+#include <linux/bitops.h>
 #include <net/sock.h>   /* for struct sock */
 #include <asm/segment.h> /* 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);
 }
 
index 46e22d50c55af0e8ca47842d6f309864953746c6..0240aa874c827147942c6b1e84d3079e78ab36df 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/atmsap.h>
 #include <linux/atmsvc.h>
 #include <linux/atmdev.h>
+#include <linux/bitops.h>
 
 #include "resources.h"
 #include "signaling.h"
 
 
 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);
-}
index dbb8c21e1504d7ba20cbce6ce1cb93185abc7961..30d5d51d4d9b08b1c3ba63eac8514db66c6bad49 100644 (file)
@@ -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
index 82ea22072a8c963c1b4f3182b9a455b02ca8ba83..47b991557dd98a41720d3107e8e5c4fc2426f5dc 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/atmsap.h>
 #include <linux/atmsvc.h>
 #include <linux/atmdev.h>
+#include <linux/bitops.h>
 #include <net/sock.h>          /* for sock_no_* */
 #include <asm/uaccess.h>
 
@@ -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();
 }
index ec59ff6220e40403d473c70f99751b76a78a8f2f..2c3d08df6069b1373a0dde5244a842928cffe429 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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
 #include <asm/uaccess.h>
 #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;
index e6fa6b379d072e532ea836012d4898d7beb75182..fc549d76a8991aa6c4d75fb665a5da87ce23ab3a 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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 <linux/if_bridge.h>
 #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);
index 084e81b4b0e318bcab540f984a3c109c1d62815d..76c14be9ccf05598432f56f34772e9b308b41622 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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);
index b09b3b9a472e7ebc9426fc7116d460eab0ed240f..f1475361899860f4b3a81aa6afddc904cd75a93a 100644 (file)
@@ -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:
index 2823c2c7e683ff34f20a6aa20a3941964ff3ab7b..c3f3b29f765d535db9dbd7d485859098872cf0c4 100644 (file)
@@ -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
index d5ca01aa6f30f895856e6f316e6c7b30023e8624..5325383218aa6bd629c71c6811a212a1a3c6e75a 100644 (file)
@@ -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 *
index 091a9eb068937d31e83e3952f12536bbf0006e24..575ec303693b539cdf6cddac16f2cee2f17d92e3 100644 (file)
@@ -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, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
index 1edee9f51bb882b166beeddce48f72187414ac3b..b6eef93a54ec55675e8846593b0de942d37a7d55 100644 (file)
@@ -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,
index c52797d70a131a99dd9e31a14e17b6b666a8a6d3..8b8db60d8febbb0f1942c799dab6cfbd7ea8b0cf 100644 (file)
@@ -6,7 +6,7 @@
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *     Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
  *
- *     $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
index a3b25f2a78ee833ae04b4e1f1fe9389cc003ae47..021d7d658ca91c20f3365a35a33a84ce51cc7eb2 100644 (file)
@@ -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);
                }
 }