]> git.pld-linux.org Git - packages/kernel.git/commitdiff
- outdated (mostly applied, remaining parts orphaned - dropping)
authorJakub Bogusz <qboosh@pld-linux.org>
Mon, 21 Aug 2006 08:53:12 +0000 (08:53 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    linux-2.4.21-atm_diffs.patch -> 1.5

linux-2.4.21-atm_diffs.patch [deleted file]

diff --git a/linux-2.4.21-atm_diffs.patch b/linux-2.4.21-atm_diffs.patch
deleted file mode 100644 (file)
index ce95a46..0000000
+++ /dev/null
@@ -1,9671 +0,0 @@
-diff -urN linux-2.4.20/arch/alpha/config.in linux-2.4.20-atm/arch/alpha/config.in
---- linux-2.4.20/arch/alpha/config.in  Wed May 28 01:53:41 2003
-+++ linux-2.4.20-atm/arch/alpha/config.in      Wed May 28 01:58:41 2003
-@@ -355,7 +355,7 @@
-   bool 'Network device support' CONFIG_NETDEVICES
-   if [ "$CONFIG_NETDEVICES" = "y" ]; then
-     source drivers/net/Config.in
--    if [ "$CONFIG_ATM" = "y" ]; then
-+    if [ "$CONFIG_ATM" != "n" ]; then
-       source drivers/atm/Config.in
-     fi
-   fi
-diff -urN linux-2.4.20/arch/cris/config.in linux-2.4.20-atm/arch/cris/config.in
---- linux-2.4.20/arch/cris/config.in   Wed May 28 01:53:41 2003
-+++ linux-2.4.20-atm/arch/cris/config.in       Wed May 28 01:58:41 2003
-@@ -199,7 +199,7 @@
-   bool 'Network device support' CONFIG_NETDEVICES
-   if [ "$CONFIG_NETDEVICES" = "y" ]; then
-     source drivers/net/Config.in
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-          source drivers/atm/Config.in
-       fi
-   fi
-diff -urN linux-2.4.20/arch/i386/config.in linux-2.4.20-atm/arch/i386/config.in
---- linux-2.4.20/arch/i386/config.in   Wed May 28 01:53:41 2003
-+++ linux-2.4.20-atm/arch/i386/config.in       Wed May 28 01:58:41 2003
-@@ -399,7 +399,7 @@
-    bool 'Network device support' CONFIG_NETDEVICES
-    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-       source drivers/net/Config.in
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-          source drivers/atm/Config.in
-       fi
-    fi
-diff -urN linux-2.4.20/arch/parisc/config.in linux-2.4.20-atm/arch/parisc/config.in
---- linux-2.4.20/arch/parisc/config.in Fri Nov 29 00:53:10 2002
-+++ linux-2.4.20-atm/arch/parisc/config.in     Wed May 28 01:58:41 2003
-@@ -136,7 +136,7 @@
-    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-       source drivers/net/Config.in
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-          source drivers/atm/Config.in
-       fi
-    fi
-diff -urN linux-2.4.20/arch/ppc/config.in linux-2.4.20-atm/arch/ppc/config.in
---- linux-2.4.20/arch/ppc/config.in    Wed May 28 01:53:43 2003
-+++ linux-2.4.20-atm/arch/ppc/config.in        Wed May 28 01:58:41 2003
-@@ -297,7 +297,7 @@
-   bool 'Network device support' CONFIG_NETDEVICES
-   if [ "$CONFIG_NETDEVICES" = "y" ]; then
-     source drivers/net/Config.in
--    if [ "$CONFIG_ATM" = "y" ]; then
-+    if [ "$CONFIG_ATM" != "n" ]; then
-       source drivers/atm/Config.in
-     fi
-   fi
-diff -urN linux-2.4.20/arch/ppc64/config.in linux-2.4.20-atm/arch/ppc64/config.in
---- linux-2.4.20/arch/ppc64/config.in  Wed May 28 01:53:44 2003
-+++ linux-2.4.20-atm/arch/ppc64/config.in      Wed May 28 01:58:41 2003
-@@ -136,7 +136,7 @@
-    bool 'Network device support' CONFIG_NETDEVICES
-    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-       source drivers/net/Config.in
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-          source drivers/atm/Config.in
-       fi
-    fi
-diff -urN linux-2.4.20/arch/sh/config.in linux-2.4.20-atm/arch/sh/config.in
---- linux-2.4.20/arch/sh/config.in     Wed May 28 01:53:44 2003
-+++ linux-2.4.20-atm/arch/sh/config.in Wed May 28 01:58:41 2003
-@@ -259,7 +259,7 @@
-    bool 'Network device support' CONFIG_NETDEVICES
-    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-       source drivers/net/Config.in
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-          source drivers/atm/Config.in
-       fi
-    fi
-diff -urN linux-2.4.20/arch/sparc/config.in linux-2.4.20-atm/arch/sparc/config.in
---- linux-2.4.20/arch/sparc/config.in  Wed May 28 01:53:44 2003
-+++ linux-2.4.20-atm/arch/sparc/config.in      Wed May 28 01:58:41 2003
-@@ -209,7 +209,7 @@
-         dep_tristate '  PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
-       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-         dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
--        if [ "$CONFIG_ATM" = "y" ]; then
-+        if [ "$CONFIG_ATM" != "n" ]; then
-           dep_tristate '  PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP
-         fi
-       fi
-@@ -235,7 +235,7 @@
- #      if [ "$CONFIG_FDDI" = "y" ]; then
- #      fi
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-        source drivers/atm/Config.in
-       fi
-    fi
-diff -urN linux-2.4.20/arch/sparc64/config.in linux-2.4.20-atm/arch/sparc64/config.in
---- linux-2.4.20/arch/sparc64/config.in        Fri Nov 29 00:53:12 2002
-+++ linux-2.4.20-atm/arch/sparc64/config.in    Wed May 28 01:58:41 2003
-@@ -234,7 +234,7 @@
-    bool 'Network device support' CONFIG_NETDEVICES
-    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-       source drivers/net/Config.in
--      if [ "$CONFIG_ATM" = "y" ]; then
-+      if [ "$CONFIG_ATM" != "n" ]; then
-       source drivers/atm/Config.in
-       fi
-    fi
-diff -urN linux-2.4.20/arch/x86_64/config.in linux-2.4.20-atm/arch/x86_64/config.in
---- linux-2.4.20/arch/x86_64/config.in Wed May 28 01:53:44 2003
-+++ linux-2.4.20-atm/arch/x86_64/config.in     Wed May 28 01:58:41 2003
-@@ -172,10 +172,9 @@
-    bool 'Network device support' CONFIG_NETDEVICES
-    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-       source drivers/net/Config.in
--# seems to be largely not 64bit safe     
--#      if [ "$CONFIG_ATM" = "y" ]; then
--#         source drivers/atm/Config.in
--#      fi
-+      if [ "$CONFIG_ATM" != "n" ]; then
-+         source drivers/atm/Config.in
-+      fi
-    fi
-    endmenu
- fi
-diff -urN linux-2.4.20/drivers/atm/Config.in linux-2.4.20-atm/drivers/atm/Config.in
---- linux-2.4.20/drivers/atm/Config.in Tue Nov 13 18:19:41 2001
-+++ linux-2.4.20-atm/drivers/atm/Config.in     Wed May 28 01:58:41 2003
-@@ -4,11 +4,11 @@
- mainmenu_option next_comment
- comment 'ATM drivers'
- if [ "$CONFIG_INET" = "y" ]; then
--   tristate 'ATM over TCP' CONFIG_ATM_TCP
-+   dep_tristate 'ATM over TCP' CONFIG_ATM_TCP $CONFIG_ATM
- fi
- if [ "$CONFIG_PCI" = "y" ]; then
--   tristate 'Efficient Networks Speedstream 3010' CONFIG_ATM_LANAI
--   tristate 'Efficient Networks ENI155P' CONFIG_ATM_ENI
-+   dep_tristate 'Efficient Networks Speedstream 3010' CONFIG_ATM_LANAI $CONFIG_ATM
-+   dep_tristate 'Efficient Networks ENI155P' CONFIG_ATM_ENI $CONFIG_ATM
-    if [ "$CONFIG_ATM_ENI" != "n" ]; then
-       bool '  Enable extended debugging' CONFIG_ATM_ENI_DEBUG
-       bool '  Fine-tune burst settings' CONFIG_ATM_ENI_TUNE_BURST
-@@ -23,8 +23,8 @@
-        bool '    Enable 2W RX bursts (optional)' CONFIG_ATM_ENI_BURST_RX_2W
-       fi
-    fi
--   tristate 'Fujitsu FireStream (FS50/FS155) ' CONFIG_ATM_FIRESTREAM
--   tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM
-+   dep_tristate 'Fujitsu FireStream (FS50/FS155) ' CONFIG_ATM_FIRESTREAM $CONFIG_ATM
-+   dep_tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM $CONFIG_ATM
-    if [ "$CONFIG_ATM_ZATM" != "n" ]; then
-       bool '  Enable extended debugging' CONFIG_ATM_ZATM_DEBUG
-       if [ "$CONFIG_X86" = "y" ]; then
-@@ -35,32 +35,32 @@
- #   if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then
- #      bool '  Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
- #   fi
--   tristate 'IDT 77201 (NICStAR) (ForeRunnerLE)' CONFIG_ATM_NICSTAR
-+   dep_tristate 'IDT 77201 (NICStAR) (ForeRunnerLE)' CONFIG_ATM_NICSTAR $CONFIG_ATM
-    if [ "$CONFIG_ATM_NICSTAR" != "n" ]; then
-       bool '  Use suni PHY driver (155Mbps)' CONFIG_ATM_NICSTAR_USE_SUNI
-       bool '  Use IDT77015 PHY driver (25Mbps)' CONFIG_ATM_NICSTAR_USE_IDT77105
-    fi
--   tristate 'IDT 77252 (NICStAR II)' CONFIG_ATM_IDT77252
-+   dep_tristate 'IDT 77252 (NICStAR II)' CONFIG_ATM_IDT77252 $CONFIG_ATM
-    if [ "$CONFIG_ATM_IDT77252" != "n" ]; then
-       bool '  Enable debugging messages' CONFIG_ATM_IDT77252_DEBUG
-       bool '  Receive ALL cells in raw queue' CONFIG_ATM_IDT77252_RCV_ALL
-       define_bool CONFIG_ATM_IDT77252_USE_SUNI y
-    fi
--   tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR
-+   dep_tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR $CONFIG_ATM
-    if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then
-       bool '  Enable debugging messages' CONFIG_ATM_AMBASSADOR_DEBUG
-    fi
--   tristate 'Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)' CONFIG_ATM_HORIZON
-+   dep_tristate 'Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)' CONFIG_ATM_HORIZON $CONFIG_ATM
-    if [ "$CONFIG_ATM_HORIZON" != "n" ]; then
-       bool '  Enable debugging messages' CONFIG_ATM_HORIZON_DEBUG
-    fi
--    tristate 'Interphase ATM PCI x575/x525/x531' CONFIG_ATM_IA
--    if [ "$CONFIG_ATM_IA" != "n" ]; then
--      bool '  Enable debugging messages' CONFIG_ATM_IA_DEBUG
--    fi
-+   dep_tristate 'Interphase ATM PCI x575/x525/x531' CONFIG_ATM_IA $CONFIG_ATM
-+   if [ "$CONFIG_ATM_IA" != "n" ]; then
-+     bool '  Enable debugging messages' CONFIG_ATM_IA_DEBUG
-+   fi
- fi
- if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
--  tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE
-+  dep_tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE $CONFIG_ATM
-   if [ "$CONFIG_ATM_FORE200E_MAYBE" != "n" ]; then
-     if [ "$CONFIG_PCI" = "y" ]; then
-       bool '  PCA-200E support' CONFIG_ATM_FORE200E_PCA
-@@ -90,6 +90,10 @@
-     else
-       define_tristate CONFIG_ATM_FORE200E m
-     fi
-+  fi
-+  dep_tristate 'ForeRunnerHE (155/622)' CONFIG_ATM_HE $CONFIG_ATM
-+  if [ "$CONFIG_ATM_HE" != "n" ] ; then
-+    bool '  Use S/UNI PHY driver' CONFIG_ATM_HE_USE_SUNI $CONFIG_ATM_HE
-   fi
- fi
- endmenu
-diff -urN linux-2.4.20/drivers/atm/Makefile linux-2.4.20-atm/drivers/atm/Makefile
---- linux-2.4.20/drivers/atm/Makefile  Wed Nov  7 23:39:36 2001
-+++ linux-2.4.20-atm/drivers/atm/Makefile      Wed May 28 01:58:41 2003
-@@ -32,6 +32,10 @@
- obj-$(CONFIG_ATM_IA) += iphase.o suni.o
- obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o
- obj-$(CONFIG_ATM_LANAI) += lanai.o
-+obj-$(CONFIG_ATM_HE) += he.o
-+ifeq ($(CONFIG_ATM_HE_USE_SUNI),y)
-+  obj-$(CONFIG_ATM_HE) += suni.o
-+endif
- ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
-   FORE200E_FW_OBJS += fore200e_pca_fw.o
-diff -urN linux-2.4.20/drivers/atm/ambassador.c linux-2.4.20-atm/drivers/atm/ambassador.c
---- linux-2.4.20/drivers/atm/ambassador.c      Fri Sep 14 00:21:32 2001
-+++ linux-2.4.20-atm/drivers/atm/ambassador.c  Wed May 28 01:58:41 2003
-@@ -1149,14 +1149,6 @@
-   }
- #endif
-   
--  // deal with possibly wildcarded VCs
--  error = atm_find_ci (atm_vcc, &vpi, &vci);
--  if (error) {
--    PRINTD (DBG_WARN|DBG_VCC, "atm_find_ci failed!");
--    return error;
--  }
--  PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
--  
-   if (!(0 <= vpi && vpi < (1<<NUM_VPI_BITS) &&
-       0 <= vci && vci < (1<<NUM_VCI_BITS))) {
-     PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci);
-diff -urN linux-2.4.20/drivers/atm/atmtcp.c linux-2.4.20-atm/drivers/atm/atmtcp.c
---- linux-2.4.20/drivers/atm/atmtcp.c  Fri Nov 29 00:53:12 2002
-+++ linux-2.4.20-atm/drivers/atm/atmtcp.c      Wed May 28 01:58:41 2003
-@@ -4,6 +4,7 @@
- #include <linux/module.h>
-+#include <linux/init.h>
- #include <linux/wait.h>
- #include <linux/atmdev.h>
- #include <linux/atm_tcp.h>
-@@ -125,8 +125,6 @@
-       msg.addr.sap_addr.vpi = vpi;
-       msg.hdr.vci = htons(vci);
-       msg.addr.sap_addr.vci = vci;
--      error = atm_find_ci(vcc,&msg.addr.sap_addr.vpi,&msg.addr.sap_addr.vci);
--      if (error) return error;
-       if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
-       msg.type = ATMTCP_CTRL_OPEN;
-       msg.qos = vcc->qos;
-@@ -155,6 +153,7 @@
- {
-       struct atm_cirange ci;
-       struct atm_vcc *vcc;
-+      struct sock *s;
-       if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
-       if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
-@@ -162,9 +161,17 @@
-       if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
-       if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
-           ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
--      for (vcc = dev->vccs; vcc; vcc = vcc->next)
-+      read_lock(&vcc_sklist_lock);
-+      for (s = vcc_sklist; s; s = s->next) {
-+              vcc = atm_sk(s);
-+              if (vcc->dev != dev) continue;
-               if ((vcc->vpi >> ci.vpi_bits) ||
--                  (vcc->vci >> ci.vci_bits)) return -EBUSY;
-+                  (vcc->vci >> ci.vci_bits)) {
-+                      read_unlock(&vcc_sklist_lock);
-+                      return -EBUSY;
-+              }
-+      }
-+      read_unlock(&vcc_sklist_lock);
-       dev->ci_range = ci;
-       return 0;
- }
-@@ -230,6 +237,7 @@
-       struct atm_dev *atmtcp_dev;
-       struct atmtcp_dev_data *dev_data;
-       struct atm_vcc *walk;
-+      struct sock *s;
-       atmtcp_dev = (struct atm_dev *) vcc->dev_data;
-       dev_data = PRIV(atmtcp_dev);
-@@ -239,8 +247,12 @@
-       kfree(dev_data);
-       shutdown_atm_dev(atmtcp_dev);
-       vcc->dev_data = NULL;
--      for (walk = atmtcp_dev->vccs; walk; walk = walk->next)
--              wake_up(&walk->sleep);
-+      read_lock(&vcc_sklist_lock);
-+      for (s = vcc_sklist; s; s = s->next) {
-+              walk = atm_sk(s);
-+              if (walk->dev == atmtcp_dev) wake_up(&walk->sleep);
-+      }
-+      read_unlock(&vcc_sklist_lock);
- }
-@@ -248,7 +260,8 @@
- {
-       struct atm_dev *dev;
-       struct atmtcp_hdr *hdr;
--      struct atm_vcc *out_vcc;
-+      struct atm_vcc *out_vcc = NULL;
-+      struct sock *s;
-       struct sk_buff *new_skb;
-       int result = 0;
-@@ -260,11 +273,17 @@
-                   (struct atmtcp_control *) skb->data);
-               goto done;
-       }
--      for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next)
-+      read_lock(&vcc_sklist_lock);
-+      for (s = vcc_sklist; s; s = s->next) {
-+              out_vcc = atm_sk(s);
-+              if (out_vcc->dev != dev) continue;
-               if (out_vcc->vpi == ntohs(hdr->vpi) &&
-                   out_vcc->vci == ntohs(hdr->vci) &&
-                   out_vcc->qos.rxtp.traffic_class != ATM_NONE)
-                       break;
-+              out_vcc = NULL;
-+      }
-+      read_unlock(&vcc_sklist_lock);
-       if (!out_vcc) {
-               atomic_inc(&vcc->stats->tx_err);
-               goto done;
-@@ -315,15 +334,10 @@
- static struct atm_dev atmtcp_control_dev = {
--      &atmtcp_c_dev_ops,
--      NULL,           /* no PHY */
--      "atmtcp",       /* type */
--      999,            /* dummy device number */
--      NULL,NULL,      /* pretend not to have any VCCs */
--      NULL,NULL,      /* no data */
--      { 0 },          /* no flags */
--      NULL,           /* no local address */
--      { 0 }           /* no ESI, no statistics */
-+      .ops            = &atmtcp_c_dev_ops,
-+      .type           = "atmtcp",
-+      .number         = 999,
-+      .lock           = SPIN_LOCK_UNLOCKED
- };
-@@ -356,9 +370,12 @@
-       struct atm_dev *dev;
-       dev = NULL;
--      if (itf != -1) dev = atm_find_dev(itf);
-+      if (itf != -1) dev = atm_dev_lookup(itf);
-       if (dev) {
--              if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
-+              if (dev->ops != &atmtcp_v_dev_ops) {
-+                      atm_dev_release(dev);
-+                      return -EMEDIUMTYPE;
-+              }
-               if (PRIV(dev)->vcc) return -EBUSY;
-       }
-       else {
-@@ -368,7 +385,7 @@
-               if (error) return error;
-       }
-       PRIV(dev)->vcc = vcc;
--      bind_vcc(vcc,&atmtcp_control_dev);
-+      vcc_insert_socket(&atmtcp_control_dev, vcc->sk);
-       set_bit(ATM_VF_META,&vcc->flags);
-       set_bit(ATM_VF_READY,&vcc->flags);
-       vcc->dev_data = dev;
-@@ -389,44 +406,42 @@
-       struct atm_dev *dev;
-       struct atmtcp_dev_data *dev_data;
--      dev = atm_find_dev(itf);
-+      dev = atm_dev_lookup(itf);
-       if (!dev) return -ENODEV;
--      if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
-+      if (dev->ops != &atmtcp_v_dev_ops) {
-+              atm_dev_release(dev);
-+              return -EMEDIUMTYPE;
-+      }
-       dev_data = PRIV(dev);
-       if (!dev_data->persist) return 0;
-       dev_data->persist = 0;
-       if (PRIV(dev)->vcc) return 0;
-       kfree(dev_data);
-+      atm_dev_release(dev);
-       shutdown_atm_dev(dev);
-       return 0;
- }
--#ifdef MODULE
-+static struct atm_tcp_ops __atm_tcp_ops = {
-+      atmtcp_attach,                  /* attach */
-+      atmtcp_create_persistent,       /* create_persistent */
-+      atmtcp_remove_persistent        /* remove_persistent */
-+};
-+
--int init_module(void)
-+static int __init atmtcp_init(void)
- {
--      atm_tcp_ops.attach = atmtcp_attach;
--      atm_tcp_ops.create_persistent = atmtcp_create_persistent;
--      atm_tcp_ops.remove_persistent = atmtcp_remove_persistent;
-+      atm_tcp_ops = &__atm_tcp_ops;
-       return 0;
- }
--
--void cleanup_module(void)
-+static void __exit atmtcp_cleanup(void)
- {
--      atm_tcp_ops.attach = NULL;
--      atm_tcp_ops.create_persistent = NULL;
--      atm_tcp_ops.remove_persistent = NULL;
-+      atm_tcp_ops = NULL;
- }
--MODULE_LICENSE("GPL");
--#else
-+module_init(atmtcp_init);
-+module_exit(atmtcp_cleanup);
--struct atm_tcp_ops atm_tcp_ops = {
--      atmtcp_attach,                  /* attach */
--      atmtcp_create_persistent,       /* create_persistent */
--      atmtcp_remove_persistent        /* remove_persistent */
--};
--
--#endif
-+MODULE_LICENSE("GPL");
-diff -urN linux-2.4.20/drivers/atm/eni.c linux-2.4.20-atm/drivers/atm/eni.c
---- linux-2.4.20/drivers/atm/eni.c     Fri Dec 21 18:41:53 2001
-+++ linux-2.4.20-atm/drivers/atm/eni.c Wed May 28 01:58:41 2003
-@@ -829,6 +829,7 @@
-       if (eni_dev->rx_map[vcc->vci])
-               printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already "
-                   "in use\n",vcc->dev->number,vcc->vci);
-+      vcc_hold(vcc);
-       eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */
-       writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) <<
-           MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE |
-@@ -858,7 +859,11 @@
-               /* discard pending cell */
-               writel(readl(here) & ~MID_VCI_IN_SERVICE,here);
-               /* don't accept any new ones */
-+              tasklet_disable(&eni_dev->task);
-               eni_dev->rx_map[vcc->vci] = NULL;
-+              barrier();
-+              tasklet_enable(&eni_dev->task);
-+              vcc_put(vcc);
-               /* wait for RX queue to drain */
-               DPRINTK("eni_close: waiting for RX ...\n");
-               EVENT("RX closing\n",0,0);
-@@ -1101,9 +1106,9 @@
-       dma_rd = eni_in(MID_DMA_RD_TX);
-       dma_size = 3; /* JK for descriptor and final fill, plus final size
-                        mis-alignment fix */
--DPRINTK("iovcnt = %d\n",ATM_SKB(skb)->iovcnt);
--      if (!ATM_SKB(skb)->iovcnt) dma_size += 5;
--      else dma_size += 5*ATM_SKB(skb)->iovcnt;
-+DPRINTK("nr_frags = %d\n", skb_shinfo(skb)->nr_frags);
-+      if (!skb_shinfo(skb)->nr_frags) dma_size += 5;
-+      else dma_size += 5*skb_shinfo(skb)->nr_frags;
-       if (dma_size > TX_DMA_BUF) {
-               printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries "
-                   "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF);
-@@ -1124,15 +1129,15 @@
-            MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
-            MID_DT_JK;
-       j++;
--      if (!ATM_SKB(skb)->iovcnt)
-+      if (!skb_shinfo(skb)->nr_frags)
-               if (aal5) put_dma(tx->index,eni_dev->dma,&j,paddr,skb->len);
-               else put_dma(tx->index,eni_dev->dma,&j,paddr+4,skb->len-4);
-       else {
- DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
--              for (i = 0; i < ATM_SKB(skb)->iovcnt; i++)
-+              for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-                       put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
--                          ((struct iovec *) skb->data)[i].iov_base,
--                          ((struct iovec *) skb->data)[i].iov_len);
-+                          skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
-+                          skb_shinfo(skb)->frags[i].size);
-       }
-       if (skb->len & 3)
-               put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
-@@ -1880,43 +1885,6 @@
- }
--static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci)
--{
--      struct atm_vcc *walk;
--
--      if (*vpi == ATM_VPI_ANY) *vpi = 0;
--      if (*vci == ATM_VCI_ANY) {
--              for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) {
--                      if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
--                          ENI_DEV(vcc->dev)->rx_map[*vci])
--                              continue;
--                      if (vcc->qos.txtp.traffic_class != ATM_NONE) {
--                              for (walk = vcc->dev->vccs; walk;
--                                  walk = walk->next)
--                                      if (test_bit(ATM_VF_ADDR,&walk->flags)
--                                          && walk->vci == *vci &&
--                                          walk->qos.txtp.traffic_class !=
--                                          ATM_NONE)
--                                              break;
--                              if (walk) continue;
--                      }
--                      break;
--              }
--              return *vci == NR_VCI ? -EADDRINUSE : 0;
--      }
--      if (*vci == ATM_VCI_UNSPEC) return 0;
--      if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
--          ENI_DEV(vcc->dev)->rx_map[*vci])
--              return -EADDRINUSE;
--      if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
--      for (walk = vcc->dev->vccs; walk; walk = walk->next)
--              if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci &&
--                  walk->qos.txtp.traffic_class != ATM_NONE)
--                      return -EADDRINUSE;
--      return 0;
--}
--
--
- static int eni_open(struct atm_vcc *vcc,short vpi,int vci)
- {
-       struct eni_dev *eni_dev;
-@@ -1927,8 +1895,6 @@
-       EVENT("eni_open\n",0,0);
-       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)
-@@ -2122,8 +2088,8 @@
- {
-       static const char *signal[] = { "LOST","unknown","okay" };
-       struct eni_dev *eni_dev = ENI_DEV(dev);
--      struct atm_vcc *vcc;
-       int left,i;
-+      struct sock *s;
-       left = *pos;
-       if (!left)
-@@ -2192,10 +2158,13 @@
-               return sprintf(page,"%10sbacklog %u packets\n","",
-                   skb_queue_len(&tx->backlog));
-       }
--      for (vcc = dev->vccs; vcc; vcc = vcc->next) {
-+      read_lock(&vcc_sklist_lock);
-+      for(s = vcc_sklist; s; s = s->next) {
-+              struct atm_vcc *vcc = atm_sk(s);
-               struct eni_vcc *eni_vcc = ENI_VCC(vcc);
-               int length;
-+              if (vcc->dev != dev) continue;
-               if (--left) continue;
-               length = sprintf(page,"vcc %4d: ",vcc->vci);
-               if (eni_vcc->rx) {
-@@ -2210,8 +2179,10 @@
-                       length += sprintf(page+length,"tx[%d], txing %d bytes",
-                           eni_vcc->tx->index,eni_vcc->txing);
-               page[length] = '\n';
-+              spin_unlock(&dev->lock);
-               return length+1;
-       }
-+      read_unlock(&vcc_sklist_lock);
-       for (i = 0; i < eni_dev->free_len; i++) {
-               struct eni_free *fe = eni_dev->free_list+i;
-               unsigned long offset;
-diff -urN linux-2.4.20/drivers/atm/firestream.c linux-2.4.20-atm/drivers/atm/firestream.c
---- linux-2.4.20/drivers/atm/firestream.c      Fri Nov 29 00:53:12 2002
-+++ linux-2.4.20-atm/drivers/atm/firestream.c  Wed May 28 01:58:41 2003
-@@ -874,12 +874,6 @@
-       fs_dprintk (FS_DEBUG_OPEN, "fs: open on dev: %p, vcc at %p\n", 
-                   dev, atm_vcc);
--      error = atm_find_ci(atm_vcc, &vpi, &vci);
--      if (error) {
--              fs_dprintk (FS_DEBUG_OPEN, "fs: find_ci failed.\n");
--              return error;
--      }
--
-       atm_vcc->vpi = vpi;
-       atm_vcc->vci = vci;
-       if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
-diff -urN linux-2.4.20/drivers/atm/fore200e.c linux-2.4.20-atm/drivers/atm/fore200e.c
---- linux-2.4.20/drivers/atm/fore200e.c        Wed May 28 01:53:45 2003
-+++ linux-2.4.20-atm/drivers/atm/fore200e.c    Wed May 28 01:58:41 2003
-@@ -65,7 +65,7 @@
- #define FORE200E_52BYTE_AAL0_SDU
- #endif
--#define FORE200E_VERSION "0.2d"
-+#define FORE200E_VERSION "0.2f"
- #define FORE200E         "fore200e: "
-@@ -1077,15 +1077,7 @@
- static struct atm_vcc* 
- fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
- {
--    struct atm_vcc* vcc;
--
--    for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
--
--      if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci)
--          break;
--    }
--    
--    return vcc;
-+    return vcc_lookup(fore200e->atm_dev, rpd->atm_header.vpi, rpd->atm_header.vci);
- }
-@@ -1132,6 +1124,7 @@
-       
-       printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
-       atomic_inc(&vcc->stats->rx_drop);
-+      vcc_put(vcc);
-       return;
-     } 
-@@ -1166,14 +1159,16 @@
-     if (atm_charge(vcc, skb->truesize) == 0) {
-       DPRINTK(2, "receive buffers saturated for %d.%d.%d - PDU dropped\n",
--              vcc->itf, vcc->vpi, vcc->vci);
-+              vcc->sk->bound_dev_if, vcc->vpi, vcc->vci);
-       dev_kfree_skb_irq(skb);
-+      vcc_put(vcc);
-       return;
-     }
-     vcc->push(vcc, skb);
-     atomic_inc(&vcc->stats->rx);
-+    vcc_put(vcc);
- }
-@@ -1215,8 +1210,8 @@
-           fore200e_push_rpd(fore200e, entry->rpd);
-       }
-       else {
--          printk(FORE200E "damaged PDU on %d.%d.%d\n", 
--                 fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
-+          DPRINTK(1, "damaged PDU on %d.%d.%d\n", 
-+                  fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci); 
-       }
-       fore200e_collect_rpd(fore200e, entry->rpd);
-@@ -1281,7 +1276,7 @@
- #endif
-     
-     DPRINTK(1, "vpvc %d.%d.%d uses the %s buffer scheme\n",
--          vcc->itf, vcc->vpi, vcc->vci, scheme == BUFFER_SCHEME_ONE ? "first" : "second");
-+          vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, scheme == BUFFER_SCHEME_ONE ? "first" : "second");
-     return scheme;
- }
-@@ -1351,39 +1346,6 @@
- }
--static int
--fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci)
--{
--    struct atm_vcc* walk;
--
--    /* find a free VPI */
--    if (*vpi == ATM_VPI_ANY) {
--
--      for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) {
--
--          if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
--              (*vpi)++;
--              walk = vcc->dev->vccs;
--          }
--      }
--    }
--
--    /* find a free VCI */
--    if (*vci == ATM_VCI_ANY) {
--      
--      for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; walk = walk->next) {
--
--          if ((walk->vpi = *vpi) && (walk->vci == *vci)) {
--              *vci = walk->vci + 1;
--              walk = vcc->dev->vccs;
--          }
--      }
--    }
--
--    return 0;
--}
--
--
- #define FORE200E_MAX_BACK2BACK_CELLS 255    /* XXX depends on CDVT */
- static void
-@@ -1408,9 +1370,6 @@
-     struct fore200e*     fore200e = FORE200E_DEV(vcc->dev);
-     struct fore200e_vcc* fore200e_vcc;
-     
--    /* find a free VPI/VCI */
--    fore200e_walk_vccs(vcc, &vpi, &vci);
--
-     vcc->vpi = vpi;
-     vcc->vci = vci;
-@@ -1419,11 +1378,11 @@
-       return 0;
-     set_bit(ATM_VF_ADDR, &vcc->flags);
--    vcc->itf    = vcc->dev->number;
-+    vcc->sk->bound_dev_if = vcc->dev->number;
-     DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
-           "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d)\n",
--          vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
-+          vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
-           fore200e_traffic_class[ vcc->qos.txtp.traffic_class ],
-           vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_cdv, vcc->qos.txtp.max_sdu,
-           fore200e_traffic_class[ vcc->qos.rxtp.traffic_class ],
-@@ -1469,7 +1428,7 @@
-       fore200e_rate_ctrl(&vcc->qos, &fore200e_vcc->rate);
-       DPRINTK(3, "tx on %d.%d.%d:%d, tx PCR = %d, rx PCR = %d, data_cells = %u, idle_cells = %u\n",
--              vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
-+              vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
-               vcc->qos.txtp.max_pcr, vcc->qos.rxtp.max_pcr, 
-               fore200e_vcc->rate.data_cells, fore200e_vcc->rate.idle_cells);
-     }
-@@ -1488,7 +1447,7 @@
- {
-     struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
-     
--    DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));
-+    DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));
-     
-     fore200e_activate_vcin(fore200e, 0, vcc, 0);
-     
-@@ -1543,7 +1502,7 @@
-     
-   retry_here:
-     
--    tasklet_disable(&fore200e->tasklet);
-+    spin_lock_bh(&fore200e->tx_lock);
-     entry = &txq->host_entry[ txq->head ];
-     
-@@ -1553,8 +1512,8 @@
-       fore200e_irq_tx(fore200e);
-       
-       if (*entry->status != STATUS_FREE) {
--          
--          tasklet_enable(&fore200e->tasklet);
-+
-+          spin_unlock_bh(&fore200e->tx_lock);
-           /* retry once again? */
-           if(--retry > 0)
-@@ -1593,8 +1552,9 @@
-       
-       entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
-       if (entry->data == NULL) {
--          
--          tasklet_enable(&fore200e->tasklet);
-+
-+          spin_unlock_bh(&fore200e->tx_lock);
-+
-           if (vcc->pop)
-               vcc->pop(vcc, skb);
-           else
-@@ -1618,13 +1578,13 @@
-     FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
-     txq->txing++;
--    tasklet_enable(&fore200e->tasklet);
-+    spin_unlock_bh(&fore200e->tx_lock);
-     /* ensure DMA synchronisation */
-     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),
-+          vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
-           tpd->tsd[0].length, skb_len);
-     if (skb_len < fore200e_vcc->tx_min_pdu)
-@@ -1690,14 +1650,14 @@
-           dev_kfree_skb(skb);
-       if (ok == 0) {
--          printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);
-+          printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->sk->bound_dev_if, 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);
-+      DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->sk->bound_dev_if, vcc->vpi, vcc->vci);
-     }
- #endif
-@@ -1755,7 +1715,7 @@
-     // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
-     DPRINTK(2, "getsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",
--          vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);
-+          vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, level, optname, optval, optlen);
-     return -EINVAL;
- }
-@@ -1767,7 +1727,7 @@
-     // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
-     
-     DPRINTK(2, "setsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",
--          vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);
-+          vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, level, optname, optval, optlen);
-     
-     return -EINVAL;
- }
-@@ -1963,7 +1923,7 @@
-           "(tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
-           "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d), flags = 0x%x\n"
-           "available_cell_rate = %u",
--          vcc->itf, vcc->vpi, vcc->vci,
-+          vcc->sk->bound_dev_if, vcc->vpi, vcc->vci,
-           fore200e_traffic_class[ qos->txtp.traffic_class ],
-           qos->txtp.min_pcr, qos->txtp.max_pcr, qos->txtp.max_cdv, qos->txtp.max_sdu,
-           fore200e_traffic_class[ qos->rxtp.traffic_class ],
-@@ -2355,6 +2315,7 @@
-     DPRINTK(2, "device %s being initialized\n", fore200e->name);
-+    spin_lock_init(&fore200e->tx_lock);
-     init_MUTEX(&fore200e->rate_sf);
-     
-     cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
-@@ -2642,6 +2603,7 @@
- {
-     struct fore200e* fore200e  = FORE200E_DEV(dev);
-     int              len, left = *pos;
-+    struct sock *s;
-     if (!left--) {
-@@ -2886,7 +2848,11 @@
-       len = sprintf(page,"\n"    
-                     " VCCs:\n  address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n");
-       
--      for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
-+      read_lock(&vcc_sklist_lock);
-+      for(s = vcc_sklist; s; s = s->next) {
-+          vcc = atm_sk(s);
-+
-+          if (vcc->dev != fore200e->atm_dev) continue;
-           fore200e_vcc = FORE200E_VCC(vcc);
-           
-@@ -2900,6 +2866,7 @@
-                          fore200e_vcc->rx_max_pdu
-               );
-       }
-+      read_unlock(&vcc_sklist_lock);
-       return len;
-     }
-diff -urN linux-2.4.20/drivers/atm/fore200e.h linux-2.4.20-atm/drivers/atm/fore200e.h
---- linux-2.4.20/drivers/atm/fore200e.h        Mon Dec 11 22:22:12 2000
-+++ linux-2.4.20-atm/drivers/atm/fore200e.h    Wed May 28 01:58:41 2003
-@@ -879,6 +879,7 @@
-     struct stats*              stats;                  /* last snapshot of the stats         */
-     
-     struct semaphore           rate_sf;                /* protects rate reservation ops      */
-+    spinlock_t                 tx_lock;                /* protects tx ops                    */
-     struct tasklet_struct      tasklet;                /* performs interrupt work            */
- } fore200e_t;
-diff -urN linux-2.4.20/drivers/atm/he.c linux-2.4.20-atm/drivers/atm/he.c
---- linux-2.4.20/drivers/atm/he.c      Thu Jan  1 01:00:00 1970
-+++ linux-2.4.20-atm/drivers/atm/he.c  Wed May 28 01:58:41 2003
-@@ -0,0 +1,3282 @@
-+/* $Id$ */
-+
-+/*
-+
-+  he.c
-+
-+  ForeRunnerHE ATM Adapter driver for ATM on Linux
-+  Copyright (C) 1999-2001  Naval Research Laboratory
-+
-+  This library is free software; you can redistribute it and/or
-+  modify it under the terms of the GNU Lesser General Public
-+  License as published by the Free Software Foundation; either
-+  version 2.1 of the License, or (at your option) any later version.
-+
-+  This library is distributed in the hope that it will be useful,
-+  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+  Lesser General Public License for more details.
-+
-+  You should have received a copy of the GNU Lesser General Public
-+  License along with this library; if not, write to the Free Software
-+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+*/
-+
-+/*
-+
-+  he.c
-+
-+  ForeRunnerHE ATM Adapter driver for ATM on Linux
-+  Copyright (C) 1999-2001  Naval Research Laboratory
-+
-+  Permission to use, copy, modify and distribute this software and its
-+  documentation is hereby granted, provided that both the copyright
-+  notice and this permission notice appear in all copies of the software,
-+  derivative works or modified versions, and any portions thereof, and
-+  that both notices appear in supporting documentation.
-+
-+  NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
-+  DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
-+  RESULTING FROM THE USE OF THIS SOFTWARE.
-+
-+  This driver was written using the "Programmer's Reference Manual for
-+  ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98.
-+
-+  AUTHORS:
-+      chas williams <chas@cmf.nrl.navy.mil>
-+      eric kinzie <ekinzie@cmf.nrl.navy.mil>
-+
-+  NOTES:
-+      4096 supported 'connections'
-+      group 0 is used for all traffic
-+      interrupt queue 0 is used for all interrupts
-+      aal0 support for receive only
-+
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/skbuff.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <linux/types.h>
-+#include <linux/string.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/mm.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/interrupt.h>
-+#include <asm/io.h>
-+#include <asm/byteorder.h>
-+#include <asm/uaccess.h>
-+
-+#include <linux/atmdev.h>
-+#include <linux/atm.h>
-+#include <linux/sonet.h>
-+#ifndef ATM_OC12_PCR
-+#define ATM_OC12_PCR (622080000/1080*1040/8/53)
-+#endif
-+
-+#ifdef BUS_INT_WAR
-+void sn_add_polled_interrupt(int irq, int interval);
-+void sn_delete_polled_interrupt(int irq);
-+#endif
-+
-+#define USE_TASKLET
-+#define USE_HE_FIND_VCC
-+#define USE_SCATTERGATHER
-+#undef USE_CHECKSUM_HW                        /* still confused about this */
-+#define USE_RBPS                      /* probably broken */
-+#define USE_RBPL_POOL
-+
-+#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
-+#define CONFIG_ATM_HE_USE_SUNI
-+#endif
-+
-+/* 2.2 kernel support */
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
-+#define dev_kfree_skb_irq(skb)                dev_kfree_skb(skb)
-+#define dev_kfree_skb_any(skb)                dev_kfree_skb(skb)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
-+#define set_current_state(x)          current->state = (x);
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
-+#undef USE_TASKLET
-+#endif
-+
-+#include "he.h"
-+
-+#include "suni.h"
-+
-+#include <linux/atm_he.h>
-+
-+#define hprintk(fmt,args...)  printk(DEV_LABEL "%d: " fmt, he_dev->number, args)
-+#define hprintk1(fmt)         printk(DEV_LABEL "%d: " fmt, he_dev->number)
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define HPRINTK(fmt,args...)  hprintk(fmt,args)
-+#define HPRINTK1(fmt)         hprintk1(fmt)
-+#else
-+#define HPRINTK(fmt,args...)
-+#define HPRINTK1(fmt,args...)
-+#endif /* DEBUG */
-+
-+
-+/* version definition */
-+
-+static char *version = "$Id$";
-+
-+/* defines */
-+#define ALIGN_ADDRESS(addr, alignment) \
-+      ((((unsigned long) (addr)) + (((unsigned long) (alignment)) - 1)) & ~(((unsigned long) (alignment)) - 1))
-+
-+/* declarations */
-+
-+static int he_open(struct atm_vcc *vcc, short vpi, int vci);
-+static void he_close(struct atm_vcc *vcc);
-+static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
-+static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size);
-+static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
-+static void he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
-+static void he_tasklet(unsigned long data);
-+static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
-+static int he_start(struct atm_dev *dev);
-+static void he_stop(struct he_dev *dev);
-+static void he_phy_put(struct atm_dev *, unsigned char, unsigned long);
-+static unsigned char he_phy_get(struct atm_dev *, unsigned long);
-+
-+static u8 read_prom_byte(struct he_dev *he_dev, int addr);
-+
-+/* globals */
-+
-+struct he_dev *he_devs = NULL;
-+static short disable64 = -1;
-+static short nvpibits = -1;
-+static short nvcibits = -1;
-+static short rx_skb_reserve = 16;
-+static short irq_coalesce = 1;
-+static short sdh = 1;
-+
-+static struct atmdev_ops he_ops =
-+{
-+   open:      he_open,
-+   close:     he_close,       
-+   ioctl:     he_ioctl,       
-+   send:      he_send,
-+   sg_send:   he_sg_send,     
-+   phy_put:   he_phy_put,
-+   phy_get:   he_phy_get,
-+   proc_read: he_proc_read,
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1)
-+   owner:     THIS_MODULE
-+#endif
-+};
-+
-+/* see the comments in he.h about global_lock */
-+
-+#ifdef CONFIG_SMP
-+#define HE_SPIN_LOCK(dev, flags)      spin_lock_irqsave(&(dev)->global_lock, flags)
-+#define HE_SPIN_UNLOCK(dev, flags)    spin_unlock_irqrestore(&(dev)->global_lock, flags)
-+#else
-+#define HE_SPIN_LOCK(dev, flags)      do { flags = 0; } while(0)
-+#define HE_SPIN_UNLOCK(dev, flags)    do { flags = 0; } while(0)
-+#endif
-+
-+
-+#define he_writel(dev, val, reg)      writel(val, (dev)->membase + (reg))
-+#define he_readl(dev, reg)            readl((dev)->membase + (reg))
-+
-+/* section 2.12 connection memory access */
-+
-+static __inline__ void
-+he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr,
-+                                                              unsigned flags)
-+{
-+      while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
-+      he_writel(he_dev, val, CON_DAT);
-+      he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL);
-+}
-+
-+#define he_writel_rcm(dev, val, reg)                          \
-+                      he_writel_internal(dev, val, reg, CON_CTL_RCM)
-+
-+#define he_writel_tcm(dev, val, reg)                          \
-+                      he_writel_internal(dev, val, reg, CON_CTL_TCM)
-+
-+#define he_writel_mbox(dev, val, reg)                                 \
-+                      he_writel_internal(dev, val, reg, CON_CTL_MBOX)
-+
-+static unsigned
-+he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
-+{
-+      while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
-+      he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL);
-+      return he_readl(he_dev, CON_DAT);
-+}
-+
-+#define he_readl_rcm(dev, reg) \
-+                      he_readl_internal(dev, reg, CON_CTL_RCM)
-+
-+#define he_readl_tcm(dev, reg) \
-+                      he_readl_internal(dev, reg, CON_CTL_TCM)
-+
-+#define he_readl_mbox(dev, reg) \
-+                      he_readl_internal(dev, reg, CON_CTL_MBOX)
-+
-+
-+/* figure 2.2 connection id */
-+
-+#define he_mkcid(dev, vpi, vci)               (((vpi<<(dev)->vcibits) | vci) & 0x1fff)
-+
-+/* 2.5.1 per connection transmit state registers */
-+
-+#define he_writel_tsr0(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 0)
-+#define he_readl_tsr0(dev, cid) \
-+              he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 0)
-+
-+#define he_writel_tsr1(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1)
-+
-+#define he_writel_tsr2(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2)
-+
-+#define he_writel_tsr3(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3)
-+
-+#define he_writel_tsr4(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4)
-+
-+      /* from page 2-20
-+       *
-+       * NOTE While the transmit connection is active, bits 23 through 0
-+       *      of this register must not be written by the host.  Byte
-+       *      enables should be used during normal operation when writing
-+       *      the most significant byte.
-+       */
-+
-+#define he_writel_tsr4_upper(dev, val, cid) \
-+              he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \
-+                                                      CON_CTL_TCM \
-+                                                      | CON_BYTE_DISABLE_2 \
-+                                                      | CON_BYTE_DISABLE_1 \
-+                                                      | CON_BYTE_DISABLE_0)
-+
-+#define he_readl_tsr4(dev, cid) \
-+              he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4)
-+
-+#define he_writel_tsr5(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5)
-+
-+#define he_writel_tsr6(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6)
-+
-+#define he_writel_tsr7(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7)
-+
-+
-+#define he_writel_tsr8(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<1) | 0)
-+
-+#define he_writel_tsr9(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<1) | 1)
-+
-+
-+#define he_writel_tsr10(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 0)
-+
-+#define he_writel_tsr11(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 1)
-+
-+#define he_writel_tsr12(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 2)
-+
-+#define he_writel_tsr13(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 3)
-+
-+
-+#define he_writel_tsr14(dev, val, cid) \
-+              he_writel_tcm(dev, val, CONFIG_TSRD | cid)
-+
-+#define he_writel_tsr14_upper(dev, val, cid) \
-+              he_writel_internal(dev, val, CONFIG_TSRD | cid, \
-+                                                      CON_CTL_TCM \
-+                                                      | CON_BYTE_DISABLE_2 \
-+                                                      | CON_BYTE_DISABLE_1 \
-+                                                      | CON_BYTE_DISABLE_0)
-+
-+/* 2.7.1 per connection receive state registers */
-+
-+#define he_writel_rsr0(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 0)
-+#define he_readl_rsr0(dev, cid) \
-+              he_readl_rcm(dev, 0x00000 | (cid<<3) | 0)
-+
-+#define he_writel_rsr1(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1)
-+
-+#define he_writel_rsr2(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2)
-+
-+#define he_writel_rsr3(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3)
-+
-+#define he_writel_rsr4(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4)
-+
-+#define he_writel_rsr5(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5)
-+
-+#define he_writel_rsr6(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6)
-+
-+#define he_writel_rsr7(dev, val, cid) \
-+              he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7)
-+
-+static __inline__ struct atm_vcc*
-+he_find_vcc(struct he_dev *he_dev, unsigned cid)
-+{
-+      short vpi;
-+      int vci;
-+
-+      vpi = cid >> he_dev->vcibits;
-+      vci = cid & ((1<<he_dev->vcibits)-1);
-+
-+      return __vcc_lookup(he_dev->atm_dev, vpi, vci);
-+}
-+
-+static int __devinit
-+he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
-+{
-+      struct atm_dev *atm_dev;
-+      struct he_dev *he_dev;
-+
-+      printk(KERN_INFO "he: %s\n", version);
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,43)
-+      if (pci_enable_device(pci_dev)) return -EIO;
-+#endif
-+      if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0)
-+      {
-+              printk(KERN_WARNING "he: no suitable dma available\n");
-+              return -EIO;
-+      }
-+
-+      atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0);
-+      if (!atm_dev) return -ENODEV;
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
-+      pci_set_drvdata(pci_dev, atm_dev);
-+#else
-+      pci_dev->driver_data = atm_dev;
-+#endif
-+
-+      he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev),
-+                                                      GFP_KERNEL);
-+      if (!he_dev) return -ENOMEM;
-+      memset(he_dev, 0, sizeof(struct he_dev));
-+
-+      he_dev->pci_dev = pci_dev;
-+      he_dev->atm_dev = atm_dev;
-+      he_dev->atm_dev->dev_data = he_dev;
-+      HE_DEV(atm_dev) = he_dev;
-+      he_dev->number = atm_dev->number;       /* was devs */
-+      if (he_start(atm_dev)) {
-+              atm_dev_deregister(atm_dev);
-+              he_stop(he_dev);
-+              kfree(he_dev);
-+              return -ENODEV;
-+      }
-+      he_dev->next = NULL;
-+      if (he_devs) he_dev->next = he_devs;
-+      he_devs = he_dev;
-+
-+      return 0;
-+}
-+
-+static void __devexit
-+he_remove_one (struct pci_dev *pci_dev)
-+{
-+      struct atm_dev *atm_dev;
-+      struct he_dev *he_dev;
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
-+      atm_dev = pci_get_drvdata(pci_dev);
-+#else
-+      atm_dev = pci_dev->driver_data;
-+#endif
-+      he_dev = HE_DEV(atm_dev);
-+
-+      /* need to remove from he_devs */
-+
-+      he_stop(he_dev);
-+      atm_dev_deregister(atm_dev);
-+      kfree(he_dev);
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
-+      pci_set_drvdata(pci_dev, NULL);
-+#else
-+      pci_dev->driver_data = NULL;
-+#endif
-+}
-+
-+
-+static unsigned
-+rate_to_atmf(unsigned rate)           /* cps to atm forum format */
-+{
-+#define NONZERO (1<<14)
-+
-+        unsigned exp = 0;
-+
-+        if (rate == 0) return(0);
-+
-+        rate <<= 9;
-+        while (rate > 0x3ff)
-+        {
-+                ++exp;
-+                rate >>= 1;
-+        }
-+
-+        return (NONZERO | (exp << 9) | (rate & 0x1ff));
-+}
-+
-+static void __init
-+he_init_rx_lbfp0(struct he_dev *he_dev)
-+{
-+        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
-+        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
-+        unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
-+        unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row;
-+        
-+      lbufd_index = 0;
-+        lbm_offset = he_readl(he_dev, RCMLBM_BA);
-+
-+      he_writel(he_dev, lbufd_index, RLBF0_H);
-+
-+        for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i)
-+        {
-+              lbufd_index += 2;
-+                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
-+
-+              he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
-+              he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
-+
-+                if (++lbuf_count == lbufs_per_row)
-+                {
-+                        lbuf_count = 0;
-+                        row_offset += he_dev->bytes_per_row;
-+                }
-+              lbm_offset += 4;
-+        }
-+                
-+        he_writel(he_dev, lbufd_index - 2, RLBF0_T);
-+      he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
-+}
-+
-+static void __init
-+he_init_rx_lbfp1(struct he_dev *he_dev)
-+{
-+        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
-+        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
-+        unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
-+        unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row;
-+        
-+      lbufd_index = 1;
-+        lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
-+
-+      he_writel(he_dev, lbufd_index, RLBF1_H);
-+
-+        for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i)
-+        {
-+              lbufd_index += 2;
-+                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
-+
-+              he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
-+              he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
-+
-+                if (++lbuf_count == lbufs_per_row)
-+                {
-+                        lbuf_count = 0;
-+                        row_offset += he_dev->bytes_per_row;
-+                }
-+              lbm_offset += 4;
-+        }
-+                
-+        he_writel(he_dev, lbufd_index - 2, RLBF1_T);
-+      he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
-+}
-+
-+static void __init
-+he_init_tx_lbfp(struct he_dev *he_dev)
-+{
-+        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
-+        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
-+        unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
-+        unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row;
-+        
-+      lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs;
-+        lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
-+
-+      he_writel(he_dev, lbufd_index, TLBF_H);
-+
-+        for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i)
-+        {
-+              lbufd_index += 1;
-+                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
-+
-+              he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
-+              he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
-+
-+                if (++lbuf_count == lbufs_per_row)
-+                {
-+                        lbuf_count = 0;
-+                        row_offset += he_dev->bytes_per_row;
-+                }
-+              lbm_offset += 2;
-+        }
-+                
-+        he_writel(he_dev, lbufd_index - 1, TLBF_T);
-+}
-+
-+static int __init
-+he_init_tpdrq(struct he_dev *he_dev)
-+{
-+      he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
-+              CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
-+      if (he_dev->tpdrq_base == NULL) 
-+      {
-+              hprintk1("failed to alloc tpdrq\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->tpdrq_base, 0,
-+                              CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
-+
-+      he_dev->tpdrq_tail = he_dev->tpdrq_base;
-+      he_dev->tpdrq_head = he_dev->tpdrq_base;
-+
-+      he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H);
-+      he_writel(he_dev, 0, TPDRQ_T);  
-+      he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S);
-+
-+      return 0;
-+}
-+
-+static void __init
-+he_init_cs_block(struct he_dev *he_dev)
-+{
-+      unsigned clock, rate, delta;
-+      int reg;
-+
-+      /* 5.1.7 cs block initialization */
-+
-+      for(reg = 0; reg < 0x20; ++reg)
-+              he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg);
-+
-+      /* rate grid timer reload values */
-+
-+      clock = he_is622(he_dev) ? 66667000 : 50000000;
-+      rate = he_dev->atm_dev->link_rate;
-+      delta = rate / 16 / 2;
-+
-+      for(reg = 0; reg < 0x10; ++reg)
-+      {
-+              /* 2.4 internal transmit function
-+               *
-+               * we initialize the first row in the rate grid.
-+               * values are period (in clock cycles) of timer
-+               */
-+              unsigned period = clock / rate;
-+
-+              he_writel_mbox(he_dev, period, CS_TGRLD0 + reg);
-+              rate -= delta;
-+      }
-+
-+      if (he_is622(he_dev))
-+      {
-+              /* table 5.2 (4 cells per lbuf) */
-+              he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0);
-+              he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1);
-+              he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2);
-+              he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3);
-+              he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4);
-+
-+              /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
-+              he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0);
-+              he_writel_mbox(he_dev, 0x1801, CS_ERCTL1);
-+              he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2);
-+              he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
-+              he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1);
-+              he_writel_mbox(he_dev, 0x14585, CS_RTFWR);
-+
-+              he_writel_mbox(he_dev, 0x4680, CS_RTATR);
-+
-+              /* table 5.8 */
-+              he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET);
-+              he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX);
-+              he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN);
-+              he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC);
-+              he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC);
-+              he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL);
-+
-+              /* table 5.9 */
-+              he_writel_mbox(he_dev, 0x5, CS_OTPPER);
-+              he_writel_mbox(he_dev, 0x14, CS_OTWPER);
-+      }
-+      else
-+      {
-+              /* table 5.1 (4 cells per lbuf) */
-+              he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0);
-+              he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1);
-+              he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2);
-+              he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3);
-+              he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4);
-+
-+              /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
-+              he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0);
-+              he_writel_mbox(he_dev, 0x4701, CS_ERCTL1);
-+              he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2);
-+              he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
-+              he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1);
-+              he_writel_mbox(he_dev, 0xf424, CS_RTFWR);
-+
-+              he_writel_mbox(he_dev, 0x4680, CS_RTATR);
-+
-+              /* table 5.8 */
-+              he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET);
-+              he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX);
-+              he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN);
-+              he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC);
-+              he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC);
-+              he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL);
-+
-+              /* table 5.9 */
-+              he_writel_mbox(he_dev, 0x6, CS_OTPPER);
-+              he_writel_mbox(he_dev, 0x1e, CS_OTWPER);
-+
-+      }
-+
-+      he_writel_mbox(he_dev, 0x8, CS_OTTLIM);
-+
-+      for(reg = 0; reg < 0x8; ++reg)
-+              he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg);
-+
-+}
-+
-+static void __init
-+he_init_cs_block_rcm(struct he_dev *he_dev)
-+{
-+      unsigned rategrid[16][16];
-+      unsigned rate, delta;
-+      int i, j, reg;
-+
-+      unsigned rate_atmf, exp, man;
-+      unsigned long long rate_cps;
-+        int mult, buf, buf_limit = 4;
-+
-+      /* initialize rate grid group table */
-+
-+      for (reg = 0x0; reg < 0xff; ++reg)
-+              he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
-+
-+      /* initialize rate controller groups */
-+
-+      for (reg = 0x100; reg < 0x1ff; ++reg)
-+              he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
-+      
-+      /* initialize tNrm lookup table */
-+
-+      /* the manual makes reference to a routine in a sample driver
-+         for proper configuration; fortunately, we only need this
-+         in order to support abr connection */
-+      
-+      /* initialize rate to group table */
-+
-+      rate = he_dev->atm_dev->link_rate;
-+      delta = rate / 32;
-+
-+      /*
-+       * 2.4 transmit internal functions
-+       * 
-+       * we construct a copy of the rate grid used by the scheduler
-+       * in order to construct the rate to group table below
-+       */
-+
-+      for (j = 0; j < 16; j++)
-+      {
-+              rategrid[0][j] = rate;
-+              rate -= delta;
-+      }
-+
-+      for (i = 1; i < 16; i++)
-+              for (j = 0; j < 16; j++)
-+                      if (i > 14)
-+                              rategrid[i][j] = rategrid[i - 1][j] / 4;
-+                      else
-+                              rategrid[i][j] = rategrid[i - 1][j] / 2;
-+
-+      /*
-+       * 2.4 transmit internal function
-+       *
-+       * this table maps the upper 5 bits of exponent and mantissa
-+       * of the atm forum representation of the rate into an index
-+       * on rate grid  
-+       */
-+
-+      rate_atmf = 0;
-+      while (rate_atmf < 0x400)
-+      {
-+              man = (rate_atmf & 0x1f) << 4;
-+              exp = rate_atmf >> 5;
-+
-+              /* 
-+                      instead of '/ 512', use '>> 9' to prevent a call
-+                      to divdu3 on x86 platforms
-+              */
-+              rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
-+
-+              if (rate_cps < 10) rate_cps = 10;
-+                              /* 2.2.1 minimum payload rate is 10 cps */
-+
-+              for (i = 255; i > 0; i--)
-+                      if (rategrid[i/16][i%16] >= rate_cps) break;
-+                              /* pick nearest rate instead? */
-+
-+              /*
-+               * each table entry is 16 bits: (rate grid index (8 bits)
-+               * and a buffer limit (8 bits)
-+               * there are two table entries in each 32-bit register
-+               */
-+
-+#ifdef notdef
-+                buf = rate_cps * he_dev->tx_numbuffs /
-+                              (he_dev->atm_dev->link_rate * 2);
-+#else
-+              /* this is pretty, but avoids _divdu3 and is mostly correct */
-+                buf = 0;
-+                mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR;
-+                if (rate_cps > (68 * mult)) buf = 1;
-+                if (rate_cps > (136 * mult)) buf = 2;
-+                if (rate_cps > (204 * mult)) buf = 3;
-+                if (rate_cps > (272 * mult)) buf = 4;
-+#endif
-+                if (buf > buf_limit) buf = buf_limit;
-+              reg = (reg<<16) | ((i<<8) | buf);
-+
-+#define RTGTBL_OFFSET 0x400
-+        
-+              if (rate_atmf & 0x1)
-+                      he_writel_rcm(he_dev, reg,
-+                              CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1));
-+
-+              ++rate_atmf;
-+      }
-+}
-+
-+
-+static int __init
-+he_init_group(struct he_dev *he_dev, int group)
-+{
-+      int i;
-+
-+#ifdef USE_RBPS
-+      /* small buffer pool */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
-+      he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
-+                      CONFIG_RBPS_BUFSIZE, 8, 0, SLAB_KERNEL);
-+#else
-+      he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
-+                      CONFIG_RBPS_BUFSIZE, 8, 0);
-+#endif
-+      if (he_dev->rbps_pool == NULL)
-+      {
-+              hprintk1("unable to create rbpl pool\n");
-+              return -ENOMEM;
-+      }
-+
-+      he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
-+              CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
-+      if (he_dev->rbps_base == NULL)
-+      {
-+              hprintk1("failed to alloc rbps\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
-+      he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
-+
-+      for (i = 0; i < CONFIG_RBPS_SIZE; ++i)
-+      {
-+              dma_addr_t dma_handle;
-+              void *cpuaddr;
-+
-+              cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
-+              if (cpuaddr == NULL)
-+                      return -ENOMEM;
-+
-+              he_dev->rbps_virt[i].virt = cpuaddr;
-+              he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
-+              he_dev->rbps_base[i].phys = dma_handle;
-+
-+      }
-+      he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1];
-+
-+      he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32));
-+      he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail),
-+                                              G0_RBPS_T + (group * 32));
-+      he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4,
-+                                              G0_RBPS_BS + (group * 32));
-+      he_writel(he_dev,
-+                      RBP_THRESH(CONFIG_RBPS_THRESH) |
-+                      RBP_QSIZE(CONFIG_RBPS_SIZE-1) |
-+                      RBP_INT_ENB,
-+                                              G0_RBPS_QI + (group * 32));
-+#else /* !USE_RBPS */
-+      he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
-+      he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
-+      he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
-+      he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
-+                                              G0_RBPS_BS + (group * 32));
-+#endif /* USE_RBPS */
-+
-+      /* large buffer pool */
-+#ifdef USE_RBPL_POOL
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
-+      he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
-+                      CONFIG_RBPL_BUFSIZE, 8, 0, SLAB_KERNEL);
-+#else
-+      he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
-+                      CONFIG_RBPL_BUFSIZE, 8, 0);
-+#endif
-+      if (he_dev->rbpl_pool == NULL)
-+      {
-+              hprintk1("unable to create rbpl pool\n");
-+              return -ENOMEM;
-+      }
-+#endif
-+
-+      he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
-+              CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
-+      if (he_dev->rbpl_base == NULL)
-+      {
-+              hprintk1("failed to alloc rbpl\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
-+      he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
-+
-+      for (i = 0; i < CONFIG_RBPL_SIZE; ++i)
-+      {
-+              dma_addr_t dma_handle;
-+              void *cpuaddr;
-+
-+#ifdef USE_RBPL_POOL
-+              cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
-+#else
-+              cpuaddr = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, &dma_handle);
-+#endif
-+              if (cpuaddr == NULL)
-+                      return -ENOMEM;
-+
-+              he_dev->rbpl_virt[i].virt = cpuaddr;
-+              he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
-+              he_dev->rbpl_base[i].phys = dma_handle;
-+
-+      }
-+      he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1];
-+
-+      he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32));
-+      he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail),
-+                                              G0_RBPL_T + (group * 32));
-+      he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4,
-+                                              G0_RBPL_BS + (group * 32));
-+      he_writel(he_dev,
-+                      RBP_THRESH(CONFIG_RBPL_THRESH) |
-+                      RBP_QSIZE(CONFIG_RBPL_SIZE-1) |
-+                      RBP_INT_ENB,
-+                                              G0_RBPL_QI + (group * 32));
-+
-+      /* rx buffer ready queue */
-+
-+      he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev,
-+              CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
-+      if (he_dev->rbrq_base == NULL)
-+      {
-+              hprintk1("failed to allocate rbrq\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
-+
-+      he_dev->rbrq_head = he_dev->rbrq_base;
-+      he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
-+      he_writel(he_dev, 0, G0_RBRQ_H + (group * 16));
-+      he_writel(he_dev,
-+              RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1),
-+                                              G0_RBRQ_Q + (group * 16));
-+      if (irq_coalesce)
-+      {
-+              hprintk1("coalescing interrupts\n");
-+              he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7),
-+                                              G0_RBRQ_I + (group * 16));
-+      }
-+      else
-+              he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1),
-+                                              G0_RBRQ_I + (group * 16));
-+
-+      /* tx buffer ready queue */
-+
-+      he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev,
-+              CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
-+      if (he_dev->tbrq_base == NULL)
-+      {
-+              hprintk1("failed to allocate tbrq\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
-+
-+      he_dev->tbrq_head = he_dev->tbrq_base;
-+
-+      he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16));
-+      he_writel(he_dev, 0, G0_TBRQ_H + (group * 16));
-+      he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16));
-+      he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
-+
-+      return 0;
-+}
-+
-+static int __init
-+he_init_irq(struct he_dev *he_dev)
-+{
-+      int i;
-+
-+      /* 2.9.3.5  tail offset for each interrupt queue is located after the
-+                  end of the interrupt queue */
-+
-+        he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev,
-+                      (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys);
-+      if (he_dev->irq_base == NULL)
-+      {
-+              hprintk1("failed to allocate irq\n");
-+              return -ENOMEM;
-+      }
-+      he_dev->irq_tailoffset = (unsigned *)
-+                                      &he_dev->irq_base[CONFIG_IRQ_SIZE];
-+      *he_dev->irq_tailoffset = 0;
-+      he_dev->irq_head = he_dev->irq_base;
-+      he_dev->irq_tail = he_dev->irq_base;
-+
-+      for(i=0; i < CONFIG_IRQ_SIZE; ++i)
-+              he_dev->irq_base[i].isw = ITYPE_INVALID;
-+
-+      he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE);
-+      he_writel(he_dev,
-+              IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH),
-+                                                              IRQ0_HEAD);
-+      he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL);
-+      he_writel(he_dev, 0x0, IRQ0_DATA);
-+
-+      he_writel(he_dev, 0x0, IRQ1_BASE);
-+      he_writel(he_dev, 0x0, IRQ1_HEAD);
-+      he_writel(he_dev, 0x0, IRQ1_CNTL);
-+      he_writel(he_dev, 0x0, IRQ1_DATA);
-+
-+      he_writel(he_dev, 0x0, IRQ2_BASE);
-+      he_writel(he_dev, 0x0, IRQ2_HEAD);
-+      he_writel(he_dev, 0x0, IRQ2_CNTL);
-+      he_writel(he_dev, 0x0, IRQ2_DATA);
-+
-+      he_writel(he_dev, 0x0, IRQ3_BASE);
-+      he_writel(he_dev, 0x0, IRQ3_HEAD);
-+      he_writel(he_dev, 0x0, IRQ3_CNTL);
-+      he_writel(he_dev, 0x0, IRQ3_DATA);
-+
-+      /* 2.9.3.2 interrupt queue mapping registers */
-+
-+      he_writel(he_dev, 0x0, GRP_10_MAP);
-+      he_writel(he_dev, 0x0, GRP_32_MAP);
-+      he_writel(he_dev, 0x0, GRP_54_MAP);
-+      he_writel(he_dev, 0x0, GRP_76_MAP);
-+
-+      if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev))
-+      {
-+              hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
-+              return -EINVAL;
-+        }   
-+
-+      he_dev->irq = he_dev->pci_dev->irq;
-+
-+#ifdef BUS_INT_WAR
-+        HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq);
-+        sn_add_polled_interrupt(he_dev->irq, 1);
-+#endif
-+
-+      return 0;
-+}
-+
-+static int __init
-+he_start(struct atm_dev *dev)
-+{
-+        struct he_dev *he_dev;
-+        struct pci_dev *pci_dev;
-+
-+      u16 command;
-+      u32 gen_cntl_0, host_cntl, lb_swap;
-+      u8 cache_size, timer;
-+      
-+      unsigned err;
-+      unsigned int status, reg;
-+      int i, group;
-+
-+        he_dev = HE_DEV(dev);
-+        pci_dev = he_dev->pci_dev;
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,3)
-+      he_dev->membase = pci_dev->resource[0].start;
-+#else
-+      he_dev->membase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
-+#endif
-+      HPRINTK("membase = 0x%x  irq = %d.\n", he_dev->membase, pci_dev->irq);
-+
-+      /*
-+       * pci bus controller initialization 
-+       */
-+
-+      /* 4.3 pci bus controller-specific initialization */
-+      if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0)
-+      {
-+              hprintk1("can't read GEN_CNTL_0\n");
-+              return -EINVAL;
-+      }
-+      gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT);
-+      if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0)
-+      {
-+              hprintk1("can't write GEN_CNTL_0.\n");
-+              return -EINVAL;
-+      }
-+
-+      if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0)
-+      {
-+              hprintk1("can't read PCI_COMMAND.\n");
-+              return -EINVAL;
-+      }
-+
-+      command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
-+      if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0)
-+      {
-+              hprintk1("can't enable memory.\n");
-+              return -EINVAL;
-+      }
-+
-+      if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size))
-+      {
-+              hprintk1("can't read cache line size?\n");
-+              return -EINVAL;
-+      }
-+
-+      if (cache_size < 16)
-+      {
-+              cache_size = 16;
-+              if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size))
-+                      hprintk("can't set cache line size to %d\n", cache_size);
-+      }
-+
-+      if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer))
-+      {
-+              hprintk1("can't read latency timer?\n");
-+              return -EINVAL;
-+      }
-+
-+      /* from table 3.9
-+       *
-+       * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE
-+       * 
-+       * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles]
-+       * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles]
-+       *
-+       */ 
-+#define LAT_TIMER 209
-+      if (timer < LAT_TIMER)
-+      {
-+              HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER);
-+              timer = LAT_TIMER;
-+              if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer))
-+                      hprintk("can't set latency timer to %d\n", timer);
-+      }
-+
-+      if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
-+              hprintk1("can't set up page mapping\n");
-+              return -EINVAL;
-+      }
-+            
-+      /* 4.4 card reset */
-+      he_writel(he_dev, 0x0, RESET_CNTL);
-+      he_writel(he_dev, 0xff, RESET_CNTL);
-+
-+      udelay(16*1000);        /* 16 ms */
-+      status = he_readl(he_dev, RESET_CNTL);
-+      if ((status & BOARD_RST_STATUS) == 0)
-+      {
-+              hprintk1("reset failed\n");
-+              return -EINVAL;
-+      }
-+
-+      /* 4.5 set bus width */
-+      host_cntl = he_readl(he_dev, HOST_CNTL);
-+      if (host_cntl & PCI_BUS_SIZE64)
-+              gen_cntl_0 |= ENBL_64;
-+      else
-+              gen_cntl_0 &= ~ENBL_64;
-+
-+      if (disable64 == 1)
-+      {
-+              hprintk1("disabling 64-bit pci bus transfers\n");
-+              gen_cntl_0 &= ~ENBL_64;
-+      }
-+
-+      if (gen_cntl_0 & ENBL_64) hprintk1("64-bit transfers enabled\n");
-+
-+      pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
-+
-+      /* 4.7 read prom contents */
-+      for(i=0; i<PROD_ID_LEN; ++i)
-+              he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i);
-+
-+      he_dev->media = read_prom_byte(he_dev, MEDIA);
-+
-+      for(i=0; i<6; ++i)
-+              dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i);
-+
-+      hprintk("%s%s, %x:%x:%x:%x:%x:%x\n",
-+                              he_dev->prod_id,
-+                                      he_dev->media & 0x40 ? "SM" : "MM",
-+                                              dev->esi[0],
-+                                              dev->esi[1],
-+                                              dev->esi[2],
-+                                              dev->esi[3],
-+                                              dev->esi[4],
-+                                              dev->esi[5]);
-+      he_dev->atm_dev->link_rate = he_is622(he_dev) ?
-+                                              ATM_OC12_PCR : ATM_OC3_PCR;
-+
-+      /* 4.6 set host endianess */
-+      lb_swap = he_readl(he_dev, LB_SWAP);
-+      if (he_is622(he_dev))
-+              lb_swap &= ~XFER_SIZE;          /* 4 cells */
-+      else
-+              lb_swap |= XFER_SIZE;           /* 8 cells */
-+#ifdef __BIG_ENDIAN
-+      lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;
-+#else
-+      lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST |
-+                      DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP);
-+#endif /* __BIG_ENDIAN */
-+      he_writel(he_dev, lb_swap, LB_SWAP);
-+
-+      /* 4.8 sdram controller initialization */
-+      he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL);
-+
-+      /* 4.9 initialize rnum value */
-+      lb_swap |= SWAP_RNUM_MAX(0xf);
-+      he_writel(he_dev, lb_swap, LB_SWAP);
-+
-+      /* 4.10 initialize the interrupt queues */
-+      if ((err = he_init_irq(he_dev)) != 0) return err;
-+
-+#ifdef USE_TASKLET
-+      tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
-+#endif
-+      spin_lock_init(&he_dev->global_lock);
-+      spin_lock_init(&he_dev->tpdrq_lock);
-+
-+      /* 4.11 enable pci bus controller state machines */
-+      host_cntl |= (OUTFF_ENB | CMDFF_ENB |
-+                              QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB);
-+      he_writel(he_dev, host_cntl, HOST_CNTL);
-+
-+      gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB;
-+      pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
-+
-+      /*
-+       * atm network controller initialization
-+       */
-+
-+      /* 5.1.1 generic configuration state */
-+
-+      /*
-+       *              local (cell) buffer memory map
-+       *                    
-+       *             HE155                          HE622
-+       *                                                      
-+       *        0 ____________1023 bytes  0 _______________________2047 bytes
-+       *         |            |            |                   |   |
-+       *         |  utility   |            |        rx0        |   |
-+       *        5|____________|         255|___________________| u |
-+       *        6|            |         256|                   | t |
-+       *         |            |            |                   | i |
-+       *         |    rx0     |     row    |        tx         | l |
-+       *         |            |            |                   | i |
-+       *         |            |         767|___________________| t |
-+       *      517|____________|         768|                   | y |
-+       * row  518|            |            |        rx1        |   |
-+       *         |            |        1023|___________________|___|
-+       *         |            |
-+       *         |    tx      |
-+       *         |            |
-+       *         |            |
-+       *     1535|____________|
-+       *     1536|            |
-+       *         |    rx1     |
-+       *     2047|____________|
-+       *
-+       */
-+
-+      /* total 4096 connections */
-+      he_dev->vcibits = CONFIG_DEFAULT_VCIBITS;
-+      he_dev->vpibits = CONFIG_DEFAULT_VPIBITS;
-+
-+      if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS)
-+      {
-+              hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS);
-+              return -ENODEV;
-+      }
-+
-+      if (nvpibits != -1)
-+      {
-+              he_dev->vpibits = nvpibits;
-+              he_dev->vcibits = HE_MAXCIDBITS - nvpibits;
-+      }
-+
-+      if (nvcibits != -1)
-+      {
-+              he_dev->vcibits = nvcibits;
-+              he_dev->vpibits = HE_MAXCIDBITS - nvcibits;
-+      }
-+
-+
-+      if (he_is622(he_dev))
-+      {
-+              he_dev->cells_per_row = 40;
-+              he_dev->bytes_per_row = 2048;
-+              he_dev->r0_numrows = 256;
-+              he_dev->tx_numrows = 512;
-+              he_dev->r1_numrows = 256;
-+              he_dev->r0_startrow = 0;
-+              he_dev->tx_startrow = 256;
-+              he_dev->r1_startrow = 768;
-+      }
-+      else
-+      {
-+              he_dev->cells_per_row = 20;
-+              he_dev->bytes_per_row = 1024;
-+              he_dev->r0_numrows = 512;
-+              he_dev->tx_numrows = 1018;
-+              he_dev->r1_numrows = 512;
-+              he_dev->r0_startrow = 6;
-+              he_dev->tx_startrow = 518;
-+              he_dev->r1_startrow = 1536;
-+      }
-+
-+      he_dev->cells_per_lbuf = 4;
-+      he_dev->buffer_limit = 4;
-+      he_dev->r0_numbuffs = he_dev->r0_numrows *
-+                              he_dev->cells_per_row / he_dev->cells_per_lbuf;
-+      if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560;
-+
-+      he_dev->r1_numbuffs = he_dev->r1_numrows *
-+                              he_dev->cells_per_row / he_dev->cells_per_lbuf;
-+      if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560;
-+
-+      he_dev->tx_numbuffs = he_dev->tx_numrows *
-+                              he_dev->cells_per_row / he_dev->cells_per_lbuf;
-+      if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120;
-+
-+      /* 5.1.2 configure hardware dependent registers */
-+
-+      he_writel(he_dev, 
-+              SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) |
-+              RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) |
-+              (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) |
-+              (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)),
-+                                                              LBARB);
-+
-+      he_writel(he_dev, BANK_ON |
-+              (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)),
-+                                                              SDRAMCON);
-+
-+      he_writel(he_dev,
-+              (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) |
-+                                              RM_RW_WAIT(1), RCMCONFIG);
-+      he_writel(he_dev,
-+              (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) |
-+                                              TM_RW_WAIT(1), TCMCONFIG);
-+
-+      he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG);
-+
-+      he_writel(he_dev, 
-+              (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) |
-+              (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) |
-+              RX_VALVP(he_dev->vpibits) |
-+              RX_VALVC(he_dev->vcibits),                       RC_CONFIG);
-+
-+      he_writel(he_dev, DRF_THRESH(0x20) |
-+              (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) |
-+              TX_VCI_MASK(he_dev->vcibits) |
-+              LBFREE_CNT(he_dev->tx_numbuffs),                TX_CONFIG);
-+
-+      he_writel(he_dev, 0x0, TXAAL5_PROTO);
-+
-+      he_writel(he_dev, PHY_INT_ENB |
-+              (he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)),
-+                                                              RH_CONFIG);
-+
-+      /* 5.1.3 initialize connection memory */
-+
-+      for(i=0; i < TCM_MEM_SIZE; ++i)
-+              he_writel_tcm(he_dev, 0, i);
-+
-+      for(i=0; i < RCM_MEM_SIZE; ++i)
-+              he_writel_rcm(he_dev, 0, i);
-+
-+      /*
-+       *      transmit connection memory map
-+       *
-+       *                  tx memory
-+       *          0x0 ___________________
-+       *             |                   |
-+       *             |                   |
-+       *             |       TSRa        |
-+       *             |                   |
-+       *             |                   |
-+       *       0x8000|___________________|
-+       *             |                   |
-+       *             |       TSRb        |
-+       *       0xc000|___________________|
-+       *             |                   |
-+       *             |       TSRc        |
-+       *       0xe000|___________________|
-+       *             |       TSRd        |
-+       *       0xf000|___________________|
-+       *             |       tmABR       |
-+       *      0x10000|___________________|
-+       *             |                   |
-+       *             |       tmTPD       |
-+       *             |___________________|
-+       *             |                   |
-+       *                      ....
-+       *      0x1ffff|___________________|
-+       *
-+       *
-+       */
-+
-+      he_writel(he_dev, CONFIG_TSRB, TSRB_BA);
-+      he_writel(he_dev, CONFIG_TSRC, TSRC_BA);
-+      he_writel(he_dev, CONFIG_TSRD, TSRD_BA);
-+      he_writel(he_dev, CONFIG_TMABR, TMABR_BA);
-+      he_writel(he_dev, CONFIG_TPDBA, TPD_BA);
-+
-+
-+      /*
-+       *      receive connection memory map
-+       *
-+       *          0x0 ___________________
-+       *             |                   |
-+       *             |                   |
-+       *             |       RSRa        |
-+       *             |                   |
-+       *             |                   |
-+       *       0x8000|___________________|
-+       *             |                   |
-+       *             |             rx0/1 |
-+       *             |       LBM         |   link lists of local
-+       *             |             tx    |   buffer memory 
-+       *             |                   |
-+       *       0xd000|___________________|
-+       *             |                   |
-+       *             |      rmABR        |
-+       *       0xe000|___________________|
-+       *             |                   |
-+       *             |       RSRb        |
-+       *             |___________________|
-+       *             |                   |
-+       *                      ....
-+       *       0xffff|___________________|
-+       */
-+
-+      he_writel(he_dev, 0x08000, RCMLBM_BA);
-+      he_writel(he_dev, 0x0e000, RCMRSRB_BA);
-+      he_writel(he_dev, 0x0d800, RCMABR_BA);
-+
-+      /* 5.1.4 initialize local buffer free pools linked lists */
-+
-+      he_init_rx_lbfp0(he_dev);
-+      he_init_rx_lbfp1(he_dev);
-+
-+      he_writel(he_dev, 0x0, RLBC_H);
-+      he_writel(he_dev, 0x0, RLBC_T);
-+      he_writel(he_dev, 0x0, RLBC_H2);
-+
-+      he_writel(he_dev, 512, RXTHRSH);        /* 10% of r0+r1 buffers */
-+      he_writel(he_dev, 256, LITHRSH);        /* 5% of r0+r1 buffers */
-+
-+      he_init_tx_lbfp(he_dev);
-+
-+      he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA);
-+
-+      /* 5.1.5 initialize intermediate receive queues */
-+
-+      if (he_is622(he_dev))
-+      {
-+              he_writel(he_dev, 0x000f, G0_INMQ_S);
-+              he_writel(he_dev, 0x200f, G0_INMQ_L);
-+
-+              he_writel(he_dev, 0x001f, G1_INMQ_S);
-+              he_writel(he_dev, 0x201f, G1_INMQ_L);
-+
-+              he_writel(he_dev, 0x002f, G2_INMQ_S);
-+              he_writel(he_dev, 0x202f, G2_INMQ_L);
-+
-+              he_writel(he_dev, 0x003f, G3_INMQ_S);
-+              he_writel(he_dev, 0x203f, G3_INMQ_L);
-+
-+              he_writel(he_dev, 0x004f, G4_INMQ_S);
-+              he_writel(he_dev, 0x204f, G4_INMQ_L);
-+
-+              he_writel(he_dev, 0x005f, G5_INMQ_S);
-+              he_writel(he_dev, 0x205f, G5_INMQ_L);
-+
-+              he_writel(he_dev, 0x006f, G6_INMQ_S);
-+              he_writel(he_dev, 0x206f, G6_INMQ_L);
-+
-+              he_writel(he_dev, 0x007f, G7_INMQ_S);
-+              he_writel(he_dev, 0x207f, G7_INMQ_L);
-+      }
-+      else
-+      {
-+              he_writel(he_dev, 0x0000, G0_INMQ_S);
-+              he_writel(he_dev, 0x0008, G0_INMQ_L);
-+
-+              he_writel(he_dev, 0x0001, G1_INMQ_S);
-+              he_writel(he_dev, 0x0009, G1_INMQ_L);
-+
-+              he_writel(he_dev, 0x0002, G2_INMQ_S);
-+              he_writel(he_dev, 0x000a, G2_INMQ_L);
-+
-+              he_writel(he_dev, 0x0003, G3_INMQ_S);
-+              he_writel(he_dev, 0x000b, G3_INMQ_L);
-+
-+              he_writel(he_dev, 0x0004, G4_INMQ_S);
-+              he_writel(he_dev, 0x000c, G4_INMQ_L);
-+
-+              he_writel(he_dev, 0x0005, G5_INMQ_S);
-+              he_writel(he_dev, 0x000d, G5_INMQ_L);
-+
-+              he_writel(he_dev, 0x0006, G6_INMQ_S);
-+              he_writel(he_dev, 0x000e, G6_INMQ_L);
-+
-+              he_writel(he_dev, 0x0007, G7_INMQ_S);
-+              he_writel(he_dev, 0x000f, G7_INMQ_L);
-+      }
-+
-+      /* 5.1.6 application tunable parameters */
-+
-+      he_writel(he_dev, 0x0, MCC);
-+      he_writel(he_dev, 0x0, OEC);
-+      he_writel(he_dev, 0x0, DCC);
-+      he_writel(he_dev, 0x0, CEC);
-+      
-+      /* 5.1.7 cs block initialization */
-+
-+      he_init_cs_block(he_dev);
-+
-+      /* 5.1.8 cs block connection memory initialization */
-+      
-+      he_init_cs_block_rcm(he_dev);
-+
-+      /* 5.1.10 initialize host structures */
-+
-+      he_init_tpdrq(he_dev);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
-+      he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
-+                      sizeof(struct he_tpd), TPD_ALIGNMENT, 0, SLAB_KERNEL);
-+#else
-+      he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
-+                      sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
-+#endif
-+      if (he_dev->tpd_pool == NULL)
-+      {
-+              hprintk1("unable to create tpd pci_pool\n");
-+              return -ENOMEM;
-+      }
-+      INIT_LIST_HEAD(&he_dev->outstanding_tpds);
-+
-+      if (he_init_group(he_dev, 0) != 0)
-+              return -ENOMEM;
-+
-+      for (group = 1; group < HE_NUM_GROUPS; ++group)
-+      {
-+              he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
-+              he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
-+              he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
-+              he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
-+                                              G0_RBPS_BS + (group * 32));
-+
-+              he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32));
-+              he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32));
-+              he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
-+                                              G0_RBPL_QI + (group * 32));
-+              he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32));
-+
-+              he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16));
-+              he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16));
-+              he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0),
-+                                              G0_RBRQ_Q + (group * 16));
-+              he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16));
-+
-+              he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16));
-+              he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16));
-+              he_writel(he_dev, TBRQ_THRESH(0x1),
-+                                              G0_TBRQ_THRESH + (group * 16));
-+              he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16));
-+      }
-+
-+      /* host status page */
-+
-+      he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,
-+                              sizeof(struct he_hsp), &he_dev->hsp_phys);
-+      if (he_dev->hsp == NULL)
-+      {
-+              hprintk1("failed to allocate host status page\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->hsp, 0, sizeof(struct he_hsp));
-+      he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
-+
-+      /* initialize framer */
-+
-+#ifdef CONFIG_ATM_HE_USE_SUNI
-+      suni_init(he_dev->atm_dev);
-+      if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start)
-+              he_dev->atm_dev->phy->start(he_dev->atm_dev);
-+#endif /* CONFIG_ATM_HE_USE_SUNI */
-+
-+      if (sdh)
-+      {
-+              /* this really should be in suni.c but for now... */
-+
-+              int val;
-+
-+              val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);
-+              val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT);
-+              he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
-+      }
-+
-+      /* 5.1.12 enable transmit and receive */
-+
-+      reg = he_readl_mbox(he_dev, CS_ERCTL0);
-+      reg |= TX_ENABLE|ER_ENABLE;
-+      he_writel_mbox(he_dev, reg, CS_ERCTL0);
-+
-+      reg = he_readl(he_dev, RC_CONFIG);
-+      reg |= RX_ENABLE;
-+      he_writel(he_dev, reg, RC_CONFIG);
-+
-+#ifndef USE_HE_FIND_VCC
-+      he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) * 
-+                      (1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL);
-+      if (he_dev->he_vcc_table == NULL)
-+      {
-+              hprintk1("failed to alloc he_vcc_table\n");
-+              return -ENOMEM;
-+      }
-+      memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) *
-+                              (1 << (he_dev->vcibits + he_dev->vpibits)));
-+#endif
-+
-+      for (i = 0; i < HE_NUM_CS_STPER; ++i)
-+      {
-+              he_dev->cs_stper[i].inuse = 0;
-+              he_dev->cs_stper[i].pcr = -1;
-+      }
-+      he_dev->total_bw = 0;
-+
-+
-+      /* atm linux initialization */
-+
-+      he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;
-+      he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;
-+
-+      he_dev->irq_peak = 0;
-+      he_dev->rbrq_peak = 0;
-+        he_dev->rbpl_peak = 0;
-+        he_dev->tbrq_peak = 0;
-+
-+      hprintk1("hell bent for leather!\n");
-+
-+      return 0;
-+}
-+
-+static void
-+he_stop(struct he_dev *he_dev)
-+{
-+      u16 command;
-+      u32 gen_cntl_0, reg;
-+      struct pci_dev *pci_dev;
-+      int i;
-+
-+      pci_dev = he_dev->pci_dev;
-+
-+      /* disable interrupts */
-+
-+      if (he_dev->membase)
-+      {
-+              pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0);
-+              gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB);
-+              pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
-+
-+#ifdef USE_TASKLET
-+              tasklet_disable(&he_dev->tasklet);
-+#endif
-+
-+              /* disable recv and transmit */
-+
-+              reg = he_readl_mbox(he_dev, CS_ERCTL0);
-+              reg &= ~(TX_ENABLE|ER_ENABLE);
-+              he_writel_mbox(he_dev, reg, CS_ERCTL0);
-+
-+              reg = he_readl(he_dev, RC_CONFIG);
-+              reg &= ~(RX_ENABLE);
-+              he_writel(he_dev, reg, RC_CONFIG);
-+      }
-+
-+#ifdef CONFIG_ATM_HE_USE_SUNI
-+      if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop)
-+              he_dev->atm_dev->phy->stop(he_dev->atm_dev);
-+#endif /* CONFIG_ATM_HE_USE_SUNI */
-+
-+      if (he_dev->irq)
-+      {
-+#ifdef BUS_INT_WAR
-+              sn_delete_polled_interrupt(he_dev->irq);
-+#endif
-+              free_irq(he_dev->irq, he_dev);
-+      }
-+
-+      if (he_dev->irq_base)
-+              pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1)
-+                      * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys);
-+
-+      if (he_dev->hsp)
-+              pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp),
-+                                              he_dev->hsp, he_dev->hsp_phys);
-+
-+      if (he_dev->rbpl_base)
-+      {
-+              for (i=0; i<CONFIG_RBPL_SIZE; ++i)
-+              {
-+                      void *cpuaddr = he_dev->rbpl_virt[i].virt;
-+                      dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
-+
-+#ifdef USE_RBPL_POOL
-+                      pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);
-+#else
-+                      pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, cpuaddr, dma_handle);
-+#endif
-+              }
-+              pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
-+                      * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
-+      }
-+
-+#ifdef USE_RBPL_POOL
-+      if (he_dev->rbpl_pool)
-+              pci_pool_destroy(he_dev->rbpl_pool);
-+#endif
-+
-+#ifdef USE_RBPS
-+      if (he_dev->rbps_base)
-+      {
-+              for (i=0; i<CONFIG_RBPS_SIZE; ++i)
-+              {
-+                      void *cpuaddr = he_dev->rbps_virt[i].virt;
-+                      dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
-+
-+                      pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);
-+              }
-+              pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
-+                      * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);
-+      }
-+#endif /* USE_RBPS */
-+
-+      if (he_dev->rbrq_base)
-+              pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
-+                                                      he_dev->rbrq_base, he_dev->rbrq_phys);
-+
-+      if (he_dev->tbrq_base)
-+              pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
-+                                                      he_dev->tbrq_base, he_dev->tbrq_phys);
-+
-+      if (he_dev->tpdrq_base)
-+              pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
-+                                                      he_dev->tpdrq_base, he_dev->tpdrq_phys);
-+
-+      if (he_dev->tpd_pool)
-+              pci_pool_destroy(he_dev->tpd_pool);
-+
-+#ifndef USE_HE_FIND_VCC
-+      if (he_dev->he_vcc_table)
-+              kfree(he_dev->he_vcc_table);
-+#endif
-+
-+      if (he_dev->pci_dev)
-+      {
-+              pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);
-+              command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-+              pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command);
-+      }
-+      
-+      if (he_dev->membase) iounmap((void *) he_dev->membase);
-+}
-+
-+static __inline__ struct he_tpd *
-+he_alloc_tpd(struct he_dev *he_dev)
-+{
-+      struct he_tpd *tpd;
-+      dma_addr_t dma_handle;
-+
-+      tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);
-+      if (tpd == NULL)
-+              return NULL;
-+
-+      tpd->status = TPD_ADDR(dma_handle);
-+      tpd->reserved = 0;
-+      tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;
-+      tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;
-+      tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0;
-+
-+      return tpd;
-+}
-+
-+
-+#define AAL5_LEN(buf,len)                                             \
-+                      ((((unsigned char *)(buf))[(len)-6]<<8) |       \
-+                              (((unsigned char *)(buf))[(len)-5]))
-+
-+/* 2.10.1.2 receive
-+ *
-+ * aal5 packets can optionally return the tcp checksum in the lower
-+ * 16 bits of the crc (RSR0_TCP_CKSUM)
-+ */
-+
-+#define TCP_CKSUM(buf,len)                                            \
-+                      ((((unsigned char *)(buf))[(len)-2]<<8) |       \
-+                              (((unsigned char *)(buf))[(len-1)]))
-+
-+static int
-+he_service_rbrq(struct he_dev *he_dev, int group)
-+{
-+      struct he_rbrq *rbrq_tail = (struct he_rbrq *)
-+                              ((unsigned long)he_dev->rbrq_base |
-+                                      he_dev->hsp->group[group].rbrq_tail);
-+      struct he_rbp *rbp = NULL;
-+      unsigned cid, lastcid = -1;
-+      unsigned buf_len = 0;
-+      struct sk_buff *skb;
-+      struct atm_vcc *vcc = NULL;
-+      struct he_vcc *he_vcc;
-+      struct iovec *iov;
-+      int pdus_assembled = 0;
-+      int updated = 0;
-+
-+      read_lock(&vcc_sklist_lock);
-+      while (he_dev->rbrq_head != rbrq_tail)
-+      {
-+              ++updated;
-+
-+              HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n",
-+                      he_dev->rbrq_head, group,
-+                      RBRQ_ADDR(he_dev->rbrq_head),
-+                      RBRQ_BUFLEN(he_dev->rbrq_head),
-+                      RBRQ_CID(he_dev->rbrq_head),
-+                      RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "",
-+                      RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "",
-+                      RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "",
-+                      RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "",
-+                      RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",
-+                      RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");
-+
-+#ifdef USE_RBPS
-+              if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)
-+                      rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
-+              else
-+#endif
-+                      rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
-+              
-+              buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
-+              cid = RBRQ_CID(he_dev->rbrq_head);
-+
-+#ifdef USE_HE_FIND_VCC
-+              if (cid != lastcid)
-+                      vcc = he_find_vcc(he_dev, cid);
-+              lastcid = cid;
-+#else
-+              vcc = HE_LOOKUP_VCC(he_dev, cid);
-+#endif
-+              if (vcc == NULL)
-+              {
-+                      hprintk("vcc == NULL  (cid 0x%x)\n", cid);
-+                      if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
-+                                      rbp->status &= ~RBP_LOANED;
-+                                      
-+                      goto next_rbrq_entry;
-+              }
-+
-+              he_vcc = HE_VCC(vcc);
-+              if (he_vcc == NULL)
-+              {
-+                      hprintk("he_vcc == NULL  (cid 0x%x)\n", cid);
-+                      if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
-+                                      rbp->status &= ~RBP_LOANED;
-+                      goto next_rbrq_entry;
-+              }
-+
-+              if (RBRQ_HBUF_ERR(he_dev->rbrq_head))
-+              {
-+                      hprintk("HBUF_ERR!  (cid 0x%x)\n", cid);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+                              ++vcc->stats->rx_drop;
-+#else
-+                              atomic_inc(&vcc->stats->rx_drop);
-+#endif
-+                      goto return_host_buffers;
-+              }
-+
-+              he_vcc->iov_tail->iov_base = (void *) RBRQ_ADDR(he_dev->rbrq_head);
-+              he_vcc->iov_tail->iov_len = buf_len;
-+              he_vcc->pdu_len += buf_len;
-+              ++he_vcc->iov_tail;
-+
-+              if (RBRQ_CON_CLOSED(he_dev->rbrq_head))
-+              {
-+                      lastcid = -1;
-+                      HPRINTK("wake_up rx_waitq  (cid 0x%x)\n", cid);
-+                      wake_up(&he_vcc->rx_waitq);
-+                      goto return_host_buffers;
-+              }
-+
-+#ifdef notdef
-+              if (he_vcc->iov_tail - he_vcc->iov_head > 32)
-+              {
-+                      hprintk("iovec full!  cid 0x%x\n", cid);
-+                      goto return_host_buffers;
-+              }
-+#endif
-+              if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry;
-+
-+              if (RBRQ_LEN_ERR(he_dev->rbrq_head)
-+                              || RBRQ_CRC_ERR(he_dev->rbrq_head))
-+              {
-+                      HPRINTK("%s%s (%d.%d)\n",
-+                              RBRQ_CRC_ERR(he_dev->rbrq_head)
-+                                                      ? "CRC_ERR " : "",
-+                              RBRQ_LEN_ERR(he_dev->rbrq_head)
-+                                                      ? "LEN_ERR" : "",
-+                                                      vcc->vpi, vcc->vci);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+                      ++vcc->stats->rx_err;
-+#else
-+                      atomic_inc(&vcc->stats->rx_err);
-+#endif
-+                      goto return_host_buffers;
-+              }
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,15)
-+              skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,
-+                                                      GFP_ATOMIC);
-+#else
-+              if (!atm_charge(vcc, atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve)))
-+                      skb = NULL;
-+              else
-+              {
-+                      skb = alloc_skb(he_vcc->pdu_len + rx_skb_reserve, GFP_ATOMIC);
-+                      if (!skb) atm_return(vcc,
-+                              atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve));
-+              }
-+#endif
-+              if (!skb)
-+              {
-+                      HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);
-+                      goto return_host_buffers;
-+              }
-+
-+              if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve);
-+
-+              do_gettimeofday(&skb->stamp);
-+
-+              for(iov = he_vcc->iov_head;
-+                              iov < he_vcc->iov_tail; ++iov)
-+              {
-+#ifdef USE_RBPS
-+                      if ((u32)iov->iov_base & RBP_SMALLBUF)
-+                              memcpy(skb_put(skb, iov->iov_len),
-+                                      he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
-+                      else
-+#endif
-+                              memcpy(skb_put(skb, iov->iov_len),
-+                                      he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
-+              }
-+
-+              switch(vcc->qos.aal)
-+              {
-+                      case ATM_AAL0:
-+                              /* 2.10.1.5 raw cell receive */
-+                              skb->len = ATM_AAL0_SDU;
-+                              skb->tail = skb->data + skb->len;
-+                              break;
-+                      case ATM_AAL5:
-+                              /* 2.10.1.2 aal5 receive */
-+
-+                              skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len);
-+                              skb->tail = skb->data + skb->len;
-+#ifdef USE_CHECKSUM_HW
-+                              if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) 
-+                              {
-+                                      skb->ip_summed = CHECKSUM_HW;
-+                                      skb->csum = TCP_CKSUM(skb->data,
-+                                                      he_vcc->pdu_len);
-+                              }
-+#endif
-+                              break;
-+              }
-+
-+#ifdef should_never_happen
-+              if (skb->len > vcc->qos.rxtp.max_sdu)
-+                      hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)!  cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid);
-+#endif
-+
-+#ifdef notdef
-+              ATM_SKB(skb)->vcc = vcc;
-+#endif
-+              vcc->push(vcc, skb);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+              ++vcc->stats->rx;
-+#else
-+              atomic_inc(&vcc->stats->rx);
-+#endif
-+
-+return_host_buffers:
-+              ++pdus_assembled;
-+
-+              for(iov = he_vcc->iov_head;
-+                              iov < he_vcc->iov_tail; ++iov)
-+              {
-+#ifdef USE_RBPS
-+                      if ((u32)iov->iov_base & RBP_SMALLBUF)
-+                              rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)];
-+                      else
-+#endif
-+                              rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)];
-+
-+                      rbp->status &= ~RBP_LOANED;
-+              }
-+
-+              he_vcc->iov_tail = he_vcc->iov_head;
-+              he_vcc->pdu_len = 0;
-+
-+next_rbrq_entry:
-+              he_dev->rbrq_head = (struct he_rbrq *)
-+                              ((unsigned long) he_dev->rbrq_base |
-+                                      RBRQ_MASK(++he_dev->rbrq_head));
-+
-+      }
-+      read_unlock(&vcc_sklist_lock);
-+
-+      if (updated)
-+      {
-+              if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated;
-+
-+              he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head),
-+                                              G0_RBRQ_H + (group * 16));
-+      }
-+
-+      return pdus_assembled;
-+}
-+
-+static void
-+he_service_tbrq(struct he_dev *he_dev, int group)
-+{
-+      struct he_tbrq *tbrq_tail = (struct he_tbrq *)
-+                              ((unsigned long)he_dev->tbrq_base |
-+                                      he_dev->hsp->group[group].tbrq_tail);
-+      struct he_tpd *tpd;
-+      int slot, updated = 0;
-+      struct list_head *list;
-+
-+      /* 2.1.6 transmit buffer return queue */
-+
-+      while (he_dev->tbrq_head != tbrq_tail)
-+      {
-+              ++updated;
-+
-+              HPRINTK("tbrq%d 0x%x%s%s\n",
-+                      group,
-+                      TBRQ_TPD(he_dev->tbrq_head), 
-+                      TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "",
-+                      TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
-+
-+              tpd = NULL;
-+              list = &he_dev->outstanding_tpds;
-+              while ((list = list->next) != &he_dev->outstanding_tpds)
-+              {
-+                      struct he_tpd *_tpd = list_entry(list, struct he_tpd, entry);
-+                      if (TPD_ADDR(_tpd->status) == TBRQ_TPD(he_dev->tbrq_head))
-+                      {
-+                              tpd = _tpd;
-+                              list_del(&_tpd->entry);
-+                              break;
-+                      }
-+              }
-+
-+              if (tpd == NULL)
-+              {
-+                      hprintk("unable to locate tpd for dma buffer %x\n",
-+                                              TBRQ_TPD(he_dev->tbrq_head));
-+                      goto next_tbrq_entry;
-+              }
-+
-+              if (TBRQ_EOS(he_dev->tbrq_head))
-+              {
-+                      HPRINTK("wake_up(tx_waitq) cid 0x%x\n",
-+                              he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci));
-+                      if (tpd->vcc)
-+                              wake_up(&HE_VCC(tpd->vcc)->tx_waitq);
-+
-+                      goto next_tbrq_entry;
-+              }
-+
-+              for(slot = 0; slot < TPD_MAXIOV; ++slot)
-+              {
-+                      if (tpd->iovec[slot].addr)
-+                              pci_unmap_single(he_dev->pci_dev,
-+                                      tpd->iovec[slot].addr,
-+                                      tpd->iovec[slot].len & TPD_LEN_MASK,
-+                                                      PCI_DMA_TODEVICE);
-+                      if (tpd->iovec[slot].len & TPD_LST) break;
-+                              
-+              }
-+
-+              if (tpd->skb)   /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */
-+              {
-+                      if (tpd->vcc && tpd->vcc->pop)
-+                              tpd->vcc->pop(tpd->vcc, tpd->skb);
-+                      else
-+                              dev_kfree_skb_any(tpd->skb);
-+              }
-+
-+
-+next_tbrq_entry:
-+              pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
-+
-+              he_dev->tbrq_head = (struct he_tbrq *)
-+                              ((unsigned long) he_dev->tbrq_base |
-+                                      TBRQ_MASK(++he_dev->tbrq_head));
-+      }
-+
-+      if (updated)
-+      {
-+              if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated;
-+
-+              he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head),
-+                                              G0_TBRQ_H + (group * 16));
-+      }
-+}
-+
-+
-+static void
-+he_service_rbpl(struct he_dev *he_dev, int group)
-+{
-+      struct he_rbp *newtail;
-+      struct he_rbp *rbpl_head;
-+      int moved = 0;
-+
-+      rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
-+                                      RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
-+
-+      for(;;)
-+      {
-+              newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
-+                                              RBPL_MASK(he_dev->rbpl_tail+1));
-+
-+              /* table 3.42 -- rbpl_tail should never be set to rbpl_head */
-+              if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED))
-+                      break;
-+
-+              newtail->status |= RBP_LOANED;
-+              he_dev->rbpl_tail = newtail;
-+              ++moved;
-+
-+      } 
-+
-+      if (moved)
-+              he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
-+}
-+
-+#ifdef USE_RBPS
-+static void
-+he_service_rbps(struct he_dev *he_dev, int group)
-+{
-+      struct he_rbp *newtail;
-+      struct he_rbp *rbps_head;
-+      int moved = 0;
-+
-+      rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
-+                                      RBPS_MASK(he_readl(he_dev, G0_RBPS_S)));
-+
-+      for(;;)
-+      {
-+              newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
-+                                              RBPS_MASK(he_dev->rbps_tail+1));
-+
-+              /* table 3.42 -- rbps_tail should never be set to rbps_head */
-+              if ((newtail == rbps_head) || (newtail->status & RBP_LOANED))
-+                      break;
-+
-+              newtail->status |= RBP_LOANED;
-+              he_dev->rbps_tail = newtail;
-+              ++moved;
-+
-+      } 
-+
-+      if (moved)
-+              he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T);
-+}
-+#endif /* USE_RBPS */
-+
-+static void
-+he_tasklet(unsigned long data)
-+{
-+      unsigned long flags;
-+      struct he_dev *he_dev = (struct he_dev *) data;
-+      int group, type;
-+      int updated = 0;
-+
-+      HPRINTK("tasklet (0x%lx)\n", data);
-+#ifdef USE_TASKLET
-+      HE_SPIN_LOCK(he_dev, flags);
-+#endif
-+
-+      while(he_dev->irq_head != he_dev->irq_tail)
-+      {
-+              ++updated;
-+
-+              type = ITYPE_TYPE(he_dev->irq_head->isw);
-+              group = ITYPE_GROUP(he_dev->irq_head->isw);
-+
-+              switch (type)
-+              {
-+                      case ITYPE_RBRQ_THRESH:
-+                              hprintk("rbrq%d threshold\n", group);
-+                      case ITYPE_RBRQ_TIMER:
-+                              if (he_service_rbrq(he_dev, group))
-+                              {
-+                                      he_service_rbpl(he_dev, group);
-+#ifdef USE_RBPS
-+                                      he_service_rbps(he_dev, group);
-+#endif /* USE_RBPS */
-+                              }
-+                              break;
-+                      case ITYPE_TBRQ_THRESH:
-+                              hprintk("tbrq%d threshold\n", group);
-+                      case ITYPE_TPD_COMPLETE:
-+                              he_service_tbrq(he_dev, group);
-+                              break;
-+                      case ITYPE_RBPL_THRESH:
-+                              he_service_rbpl(he_dev, group);
-+                              break;
-+                      case ITYPE_RBPS_THRESH:
-+#ifdef USE_RBPS
-+                              he_service_rbps(he_dev, group);
-+#endif /* USE_RBPS */
-+                              break;
-+                      case ITYPE_PHY:
-+#ifdef CONFIG_ATM_HE_USE_SUNI
-+                              if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt)
-+                                      he_dev->atm_dev->phy->interrupt(he_dev->atm_dev);
-+#endif
-+                              HPRINTK1("phy interrupt\n");
-+                              break;
-+                      case ITYPE_OTHER:
-+                              switch (type|group)
-+                              {
-+                                      case ITYPE_PARITY:
-+                                              hprintk1("parity error\n");
-+                                              break;
-+                                      case ITYPE_ABORT:
-+                                              hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR));
-+                                              break;
-+                              }
-+                              break;
-+                      default:
-+                              if (he_dev->irq_head->isw == ITYPE_INVALID)
-+                              {
-+                                      /* see 8.1.1 -- check all queues */
-+
-+                                      HPRINTK("isw not updated 0x%x\n",
-+                                              he_dev->irq_head->isw);
-+
-+                                      he_service_rbrq(he_dev, 0);
-+                                      he_service_rbpl(he_dev, 0);
-+#ifdef USE_RBPS
-+                                      he_service_rbps(he_dev, 0);
-+#endif /* USE_RBPS */
-+                                      he_service_tbrq(he_dev, 0);
-+                              }
-+                              else
-+                                      hprintk("bad isw = 0x%x?\n",
-+                                              he_dev->irq_head->isw);
-+              }
-+
-+              he_dev->irq_head->isw = ITYPE_INVALID;
-+
-+              he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK);
-+      }
-+
-+      if (updated)
-+      {
-+              if (updated > he_dev->irq_peak) he_dev->irq_peak = updated;
-+
-+              he_writel(he_dev,
-+                      IRQ_SIZE(CONFIG_IRQ_SIZE) |
-+                      IRQ_THRESH(CONFIG_IRQ_THRESH) |
-+                      IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD);
-+              (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
-+      }
-+#ifdef USE_TASKLET
-+      HE_SPIN_UNLOCK(he_dev, flags);
-+#endif
-+}
-+
-+static void
-+he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      unsigned long flags;
-+      struct he_dev *he_dev = (struct he_dev * )dev_id;
-+
-+      if (he_dev == NULL) return;
-+
-+      HE_SPIN_LOCK(he_dev, flags);
-+
-+      he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) |
-+                                              (*he_dev->irq_tailoffset << 2));
-+
-+      if (he_dev->irq_tail == he_dev->irq_head)
-+      {
-+              HPRINTK1("tailoffset not updated?\n");
-+              he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base |
-+                      ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2));
-+              (void) he_readl(he_dev, INT_FIFO);      /* 8.1.2 controller errata */
-+      }
-+
-+#ifdef notdef
-+      if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */)
-+              hprintk1("spurious interrupt?\n");
-+#endif
-+
-+      if (he_dev->irq_head != he_dev->irq_tail)
-+      {
-+#ifdef USE_TASKLET
-+              tasklet_schedule(&he_dev->tasklet);
-+#else
-+              he_tasklet((unsigned long) he_dev);
-+#endif
-+              he_writel(he_dev, INT_CLEAR_A, INT_FIFO);
-+                                                      /* clear interrupt */
-+      }
-+
-+      HE_SPIN_UNLOCK(he_dev, flags);
-+}
-+
-+static __inline__ void
-+he_enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
-+{
-+      struct he_tpdrq *new_tail;
-+      unsigned flags;
-+
-+      spin_lock_irqsave(&he_dev->tpdrq_lock, flags);
-+
-+      HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n",
-+                                      tpd, cid, he_dev->tpdrq_tail);
-+
-+      new_tail = he_dev->tpdrq_tail;
-+      new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base |
-+                                      TPDRQ_MASK(++new_tail));
-+
-+      /*
-+       * check to see if we are about to set the tail == head
-+       * if true, update the head pointer from the adapter
-+       * to see if this is really the case (reading the queue
-+       * head for every enqueue would be unnecessarily slow)
-+       */
-+
-+      if (new_tail == he_dev->tpdrq_head)
-+      {
-+              he_dev->tpdrq_head = (struct he_tpdrq *)
-+                      (((unsigned long)he_dev->tpdrq_base) |
-+                              TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H)));
-+
-+              if (new_tail == he_dev->tpdrq_head)
-+              {
-+                      hprintk("tpdrq full (cid 0x%x)\n", cid);
-+                      /*
-+                       * FIXME
-+                       * push tpd onto a transmit backlog queue
-+                       * after service_tbrq, service the backlog
-+                       * for now, we just drop the pdu
-+                       */
-+                      if (tpd->skb)
-+                      {
-+                              if (tpd->vcc->pop)
-+                                      tpd->vcc->pop(tpd->vcc, tpd->skb);
-+                              else
-+                                      dev_kfree_skb_any(tpd->skb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+                              ++tpd->vcc->stats->tx_err;
-+#else
-+                              atomic_inc(&tpd->vcc->stats->tx_err);
-+#endif
-+                      }
-+                      pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
-+                      spin_unlock_irqrestore(&he_dev->tpdrq_lock, flags);
-+                      return;
-+              }
-+      }
-+
-+      /* 2.1.5 transmit packet descriptor ready queue */
-+      he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status);
-+      he_dev->tpdrq_tail->cid = cid;
-+      mb();
-+      list_add_tail(&tpd->entry, &he_dev->outstanding_tpds);
-+
-+      he_dev->tpdrq_tail = new_tail;
-+
-+      he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T);
-+      spin_unlock_irqrestore(&he_dev->tpdrq_lock, flags);
-+}
-+
-+static int
-+he_open(struct atm_vcc *vcc, short vpi, int vci)
-+{
-+      unsigned long flags;
-+      struct he_dev *he_dev = HE_DEV(vcc->dev);
-+      struct he_vcc *he_vcc;
-+      int err = 0;
-+      unsigned cid, rsr0, rsr1, rsr4, tsr0, period, reg, clock;
-+      int first_open = 0;
-+
-+      if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0;
-+      vcc->vpi = vpi;
-+      vcc->vci = vci;
-+
-+      HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+      vcc->flags |= ATM_VF_ADDR;
-+#else
-+      set_bit(ATM_VF_ADDR, &vcc->flags);
-+#endif
-+
-+      cid = he_mkcid(he_dev, vpi, vci);
-+
-+      he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_KERNEL);
-+      if (he_vcc == NULL)
-+      {
-+              hprintk1("unable to allocate he_vcc during open\n");
-+              return -ENOMEM;
-+      }
-+
-+      he_vcc->iov_tail = he_vcc->iov_head;
-+      he_vcc->pdu_len = 0;
-+      he_vcc->rc_index = -1;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+      init_waitqueue(&he_vcc->rx_waitq);
-+      init_waitqueue(&he_vcc->tx_waitq);
-+#else
-+      init_waitqueue_head(&he_vcc->rx_waitq);
-+      init_waitqueue_head(&he_vcc->tx_waitq);
-+#endif
-+
-+      HE_VCC(vcc) = he_vcc;
-+
-+      if (vcc->qos.txtp.traffic_class != ATM_NONE)
-+      {
-+              int pcr_goal;
-+
-+                pcr_goal = atm_pcr_goal(&vcc->qos.txtp);
-+                if (pcr_goal == 0)
-+                        pcr_goal = he_dev->atm_dev->link_rate;
-+                if (pcr_goal < 0)     /* means round down, technically */
-+                        pcr_goal = -pcr_goal;
-+
-+              HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal);
-+
-+              /* no transmit support for AAL0 -- FIXME */
-+
-+              if (vcc->qos.aal != ATM_AAL5)
-+              {
-+                      err = -EINVAL;
-+                      goto open_failed;
-+              }
-+
-+              HE_SPIN_LOCK(he_dev, flags);
-+              tsr0 = he_readl_tsr0(he_dev, cid);
-+              HE_SPIN_UNLOCK(he_dev, flags);
-+
-+              if (tsr0 == 0 && vcc->qos.aal == ATM_AAL5) first_open = 1;
-+
-+              if (TSR0_CONN_STATE(tsr0) != 0)
-+              {
-+                      hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0);
-+#ifdef notdef
-+                      err = -EBUSY;
-+                      goto open_failed;
-+#endif
-+              }
-+
-+              switch(vcc->qos.txtp.traffic_class)
-+              {
-+                      case ATM_UBR:
-+                              /* 2.3.3.1 open connection ubr */
-+
-+                              tsr0 = TSR0_UBR | TSR0_GROUP(0) | TSR0_AAL5 |
-+                                      TSR0_USE_WMIN | TSR0_UPDATE_GER;
-+                              break;
-+
-+                      case ATM_CBR:
-+                              /* 2.3.3.2 open connection cbr */
-+
-+                              clock = he_is622(he_dev) ? 66667000 : 50000000;
-+                              period = clock / pcr_goal;
-+                              
-+                              /* find an unused cs_stper register */
-+
-+                              for(reg = 0; reg < HE_NUM_CS_STPER; ++reg)
-+                                      if (he_dev->cs_stper[reg].inuse == 0 || 
-+                                              he_dev->cs_stper[reg].pcr == pcr_goal)
-+                                      break;
-+
-+                              if (reg == HE_NUM_CS_STPER)
-+                              {
-+                                      err = -EBUSY;
-+                                      goto open_failed;
-+                              }
-+
-+                              /* 8.2.3 cbr scheduler wrap problem */
-+                              if ((he_dev->total_bw + pcr_goal)
-+                                      > (he_dev->atm_dev->link_rate * 10 / 9))
-+                              {
-+                                      err = -EBUSY;
-+                                      goto open_failed;
-+                              }
-+                              he_dev->total_bw += pcr_goal;
-+
-+                              he_vcc->rc_index = reg;
-+                              ++he_dev->cs_stper[reg].inuse;
-+                              he_dev->cs_stper[reg].pcr = pcr_goal;
-+
-+                              HPRINTK("rc_index = %d period = %d\n",
-+                                                              reg, period);
-+
-+                              HE_SPIN_LOCK(he_dev, flags);
-+                              he_writel_mbox(he_dev, rate_to_atmf(period/2),
-+                                                      CS_STPER0 + reg);
-+                              HE_SPIN_UNLOCK(he_dev, flags);
-+
-+                              tsr0 = TSR0_CBR | TSR0_GROUP(0) | TSR0_AAL5 |
-+                                                      TSR0_RC_INDEX(reg);
-+
-+                              break;
-+                      default:
-+                              err = -EINVAL;
-+                              goto open_failed;
-+              }
-+
-+              HE_SPIN_LOCK(he_dev, flags);
-+
-+              he_writel_tsr0(he_dev, tsr0, cid);
-+              he_writel_tsr4(he_dev, TSR4_AAL5 | 1, cid);
-+              he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) |
-+                                      TSR1_PCR(rate_to_atmf(pcr_goal)), cid);
-+              he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid);
-+              he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid);
-+
-+              he_writel_tsr3(he_dev, 0x0, cid);
-+              he_writel_tsr5(he_dev, 0x0, cid);
-+              he_writel_tsr6(he_dev, 0x0, cid);
-+              he_writel_tsr7(he_dev, 0x0, cid);
-+              he_writel_tsr8(he_dev, 0x0, cid);
-+              he_writel_tsr10(he_dev, 0x0, cid);
-+              he_writel_tsr11(he_dev, 0x0, cid);
-+              he_writel_tsr12(he_dev, 0x0, cid);
-+              he_writel_tsr13(he_dev, 0x0, cid);
-+              he_writel_tsr14(he_dev, 0x0, cid);
-+
-+              /* work around:
-+               *
-+               * the first aal5 pdu sent always seems to have a bad
-+               * crc.  no idea why. probably initializing the card 
-+               * wrong?  if tsr0 == 0 this is the first open after
-+               * a reset.
-+               */
-+                  
-+              if (first_open)
-+              {
-+#define BADCRCMESG "BAD CRC WORKAROUND"
-+                      static char *badcrc = NULL;
-+                      struct he_tpd *tpd;
-+
-+                      tpd = he_alloc_tpd(he_dev);
-+ 
-+                      if (!badcrc)
-+                      { 
-+                              badcrc = kmalloc(strlen(BADCRCMESG), GFP_DMA);
-+                              memcpy(badcrc, BADCRCMESG, strlen(BADCRCMESG));
-+                      } 
-+
-+                        HPRINTK("bad crc workaround cid = 0x%x\n", cid);
-+
-+                      tpd->address0 = pci_map_single(he_dev->pci_dev,
-+                              badcrc, strlen(BADCRCMESG), PCI_DMA_TODEVICE);
-+                      tpd->length0 = strlen(BADCRCMESG) | TPD_LST;
-+                      tpd->status |= TPD_USERCELL | TPD_INT;
-+                      mb();
-+                      tpd->skb = NULL;
-+                      tpd->vcc = vcc;
-+
-+                      he_enqueue_tpd(he_dev, tpd, cid);
-+              }
-+
-+              HE_SPIN_UNLOCK(he_dev, flags);
-+      }
-+
-+      if (vcc->qos.rxtp.traffic_class != ATM_NONE)
-+      {
-+              unsigned aal;
-+
-+              HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid,
-+                                              &HE_VCC(vcc)->rx_waitq);
-+
-+              switch (vcc->qos.aal)
-+              {
-+                      case ATM_AAL5:
-+                              aal = RSR0_AAL5;
-+                              break;
-+                      case ATM_AAL0:
-+                              aal = RSR0_RAWCELL;
-+                              break;
-+                      default:
-+                              err = -EINVAL;
-+                              goto open_failed;
-+              }
-+
-+              HE_SPIN_LOCK(he_dev, flags);
-+
-+              rsr0 = he_readl_rsr0(he_dev, cid);
-+              if (rsr0 & RSR0_OPEN_CONN)
-+              {
-+                      HE_SPIN_UNLOCK(he_dev, flags);
-+
-+                      hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0);
-+                      err = -EBUSY;
-+                      goto open_failed;
-+              }
-+
-+#ifdef USE_RBPS
-+              rsr1 = RSR1_GROUP(0);
-+              rsr4 = RSR4_GROUP(0);
-+#else /* !USE_RBPS */
-+              rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY;
-+              rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY;
-+#endif /* USE_RBPS */
-+              rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? 
-+                              (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0;
-+
-+#ifdef USE_CHECKSUM_HW
-+              if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM;
-+#endif
-+
-+              he_writel_rsr4(he_dev, rsr4, cid);
-+              he_writel_rsr1(he_dev, rsr1, cid);
-+              /* 5.1.11 last parameter initialized should be
-+                        the open/closed indication in rsr0 */
-+              he_writel_rsr0(he_dev,
-+                      rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid);
-+
-+              HE_SPIN_UNLOCK(he_dev, flags);
-+
-+#ifndef USE_HE_FIND_VCC
-+              HE_LOOKUP_VCC(he_dev, cid) = vcc;
-+#endif
-+      }
-+
-+open_failed:
-+
-+      if (err)
-+      {
-+              if (he_vcc) kfree(he_vcc);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+              vcc->flags &= ~ATM_VF_ADDR;
-+#else
-+              clear_bit(ATM_VF_ADDR, &vcc->flags);
-+#endif
-+      }
-+      else
-+      {
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+              vcc->flags |= ATM_VF_READY;
-+#else
-+              set_bit(ATM_VF_READY, &vcc->flags);
-+#endif
-+      }
-+
-+      return err;
-+}
-+
-+static void
-+he_close(struct atm_vcc *vcc)
-+{
-+      unsigned long flags;
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
-+      DECLARE_WAITQUEUE(wait, current);
-+#else
-+      struct wait_queue wait = { current, NULL };
-+#endif
-+      struct he_dev *he_dev = HE_DEV(vcc->dev);
-+      struct he_tpd *tpd;
-+      unsigned cid;
-+      struct he_vcc *he_vcc = HE_VCC(vcc);
-+#define MAX_RETRY 30
-+      int retry = 0, sleep = 1, tx_inuse;
-+
-+      HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+      vcc->flags &= ~ATM_VF_READY;
-+#else
-+      clear_bit(ATM_VF_READY, &vcc->flags);
-+#endif
-+      cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
-+
-+      HE_SPIN_LOCK(he_dev, flags);
-+
-+      if (vcc->qos.rxtp.traffic_class != ATM_NONE)
-+      {
-+              int timeout;
-+
-+              HPRINTK("close rx cid 0x%x\n", cid);
-+
-+              /* 2.7.2.2 close receive operation */
-+
-+              /* wait for previous close (if any) to finish */
-+
-+              while(he_readl(he_dev, RCC_STAT) & RCC_BUSY)
-+              {
-+                      HPRINTK("close cid 0x%x RCC_BUSY\n", cid);
-+                      udelay(250);
-+              }
-+
-+              add_wait_queue(&he_vcc->rx_waitq, &wait);
-+              set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+              he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
-+              he_writel_mbox(he_dev, cid, RXCON_CLOSE);
-+
-+              HE_SPIN_UNLOCK(he_dev, flags);
-+              timeout = schedule_timeout(30*HZ);
-+              HE_SPIN_LOCK(he_dev, flags);
-+              remove_wait_queue(&he_vcc->rx_waitq, &wait);
-+              set_current_state(TASK_RUNNING);
-+
-+              if (timeout == 0)
-+                      hprintk("close rx timeout cid 0x%x\n", cid);
-+
-+#ifndef USE_HE_FIND_VCC
-+              HE_LOOKUP_VCC(he_dev, cid) = NULL;
-+#endif
-+              HPRINTK("close rx cid 0x%x complete\n", cid);
-+
-+      }
-+
-+      if (vcc->qos.txtp.traffic_class != ATM_NONE)
-+      {
-+              volatile unsigned tsr4, tsr0;
-+              int timeout;
-+
-+              HPRINTK("close tx cid 0x%x\n", cid);
-+              
-+              /* 2.1.2
-+               *
-+               * ... the host must first stop queueing packets to the TPDRQ
-+               * on the connection to be closed, then wait for all outstanding
-+               * packets to be transmitted and their buffers returned to the
-+               * TBRQ. When the last packet on the connection arrives in the
-+               * TBRQ, the host issues the close command to the adapter.
-+               */
-+
-+              HE_SPIN_UNLOCK(he_dev, flags);
-+              while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0)
-+                                                      && (retry < MAX_RETRY))
-+              {
-+                      set_current_state(TASK_UNINTERRUPTIBLE);
-+                      (void) schedule_timeout(sleep);
-+                      set_current_state(TASK_RUNNING);
-+                      if (sleep < HZ) sleep = sleep * 2;
-+
-+                      ++retry;
-+              }
-+
-+              if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n",
-+                                                              cid, tx_inuse);
-+              HE_SPIN_LOCK(he_dev, flags);
-+
-+              /* 2.3.1.1 generic close operations with flush */
-+
-+              he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid);
-+                                      /* also clears TSR4_SESSION_ENDED */
-+
-+              switch(vcc->qos.txtp.traffic_class)
-+              {
-+                      case ATM_UBR:
-+                              he_writel_tsr1(he_dev, 
-+                                      TSR1_MCR(rate_to_atmf(200000))
-+                                      | TSR1_PCR(0), cid);
-+                              break;
-+                      case ATM_CBR:
-+                              he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid);
-+                              break;
-+              }
-+
-+
-+              tpd = he_alloc_tpd(he_dev);
-+              if (tpd == NULL)
-+              {
-+                      hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid);
-+                      goto close_tx_incomplete;
-+              }
-+              tpd->status |= TPD_EOS | TPD_INT;
-+              tpd->skb = NULL;
-+              tpd->vcc = vcc;
-+              mb();
-+
-+              add_wait_queue(&he_vcc->tx_waitq, &wait);
-+              set_current_state(TASK_UNINTERRUPTIBLE);
-+              he_enqueue_tpd(he_dev, tpd, cid);
-+              HE_SPIN_UNLOCK(he_dev, flags);
-+              timeout = schedule_timeout(30*HZ);
-+              HE_SPIN_LOCK(he_dev, flags);
-+              remove_wait_queue(&he_vcc->tx_waitq, &wait);
-+              set_current_state(TASK_RUNNING);
-+
-+              if (timeout == 0)
-+              {
-+                      hprintk("close tx timeout cid 0x%x\n", cid);
-+                      goto close_tx_incomplete;
-+              }
-+
-+              while (!((tsr4 = he_readl_tsr4(he_dev, cid))
-+                                                      & TSR4_SESSION_ENDED))
-+              {
-+                      HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4);
-+                      udelay(250);
-+              }
-+
-+              while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0)
-+              {
-+                      HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0);
-+                      udelay(250);
-+              }
-+
-+close_tx_incomplete:
-+
-+              if (vcc->qos.txtp.traffic_class == ATM_CBR)
-+              {
-+                      int reg = he_vcc->rc_index;
-+
-+                      HPRINTK("cs_stper reg = %d\n", reg);
-+
-+                      if (he_dev->cs_stper[reg].inuse == 0)
-+                              hprintk("cs_stper[%d].inuse = 0!\n", reg);
-+                      else
-+                              --he_dev->cs_stper[reg].inuse;
-+
-+                      he_dev->total_bw -= he_dev->cs_stper[reg].pcr;
-+              }
-+
-+              HPRINTK("close tx cid 0x%x complete\n", cid);
-+      }
-+
-+      kfree(he_vcc);
-+      HE_SPIN_UNLOCK(he_dev, flags);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+      vcc->flags &= ~ATM_VF_ADDR;
-+#else
-+      clear_bit(ATM_VF_ADDR, &vcc->flags);
-+#endif
-+}
-+
-+static int
-+he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size)
-+{
-+#ifdef USE_SCATTERGATHER
-+      return 1;
-+#else
-+      return 0;
-+#endif
-+}
-+
-+static int
-+he_send(struct atm_vcc *vcc, struct sk_buff *skb)
-+{
-+      unsigned long flags;
-+      struct he_dev *he_dev = HE_DEV(vcc->dev);
-+      unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
-+      struct he_tpd *tpd;
-+#ifdef USE_SCATTERGATHER
-+      int i, slot = 0;
-+#endif
-+
-+#define HE_TPD_BUFSIZE 0xffff
-+
-+      HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci);
-+
-+      if (skb->len > HE_TPD_BUFSIZE )
-+      {
-+              hprintk("buffer too large (%d bytes)\n", skb->len );
-+              if (vcc->pop)
-+                      vcc->pop(vcc, skb);
-+              else
-+                      dev_kfree_skb_any(skb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+              ++vcc->stats->tx_err;
-+#else
-+              atomic_inc(&vcc->stats->tx_err);
-+#endif
-+              return -EINVAL;
-+      }
-+
-+#ifndef USE_SCATTERGATHER
-+      if (skb_shinfo(skb)->nr_frags)
-+      {
-+              hprintk1("no scatter/gather support\n");
-+              if (vcc->pop)
-+                      vcc->pop(vcc, skb);
-+              else
-+                      dev_kfree_skb_any(skb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+              ++vcc->stats->tx_err;
-+#else
-+              atomic_inc(&vcc->stats->tx_err);
-+#endif
-+              return -EINVAL;
-+      }
-+#endif
-+
-+      tpd = he_alloc_tpd(he_dev);
-+      if (tpd == NULL)
-+      {
-+              if (vcc->pop)
-+                      vcc->pop(vcc, skb);
-+              else
-+                      dev_kfree_skb_any(skb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+              ++vcc->stats->tx_err;
-+#else
-+              atomic_inc(&vcc->stats->tx_err);
-+#endif
-+              return -ENOMEM;
-+      }
-+      tpd->status |= TPD_USERCELL;
-+
-+#ifdef USE_SCATTERGATHER
-+      tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data,
-+                              skb->len - skb->data_len, PCI_DMA_TODEVICE);
-+      tpd->iovec[slot].len = skb->len - skb->data_len;
-+      ++slot;
-+
-+      for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-+      {
-+              skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-+
-+              if (slot == TPD_MAXIOV)         /* send tpd; start new tpd */
-+              {
-+                      tpd->vcc = vcc;
-+                      tpd->skb = NULL;        /* not the last fragment
-+                                                 so dont ->push() yet */
-+                      mb();
-+
-+                      HE_SPIN_LOCK(he_dev, flags);
-+                      he_enqueue_tpd(he_dev, tpd, cid);
-+                      HE_SPIN_UNLOCK(he_dev, flags);
-+                      tpd = he_alloc_tpd(he_dev);
-+                      if (tpd == NULL)
-+                      {
-+                              if (vcc->pop)
-+                                      vcc->pop(vcc, skb);
-+                              else
-+                                      dev_kfree_skb_any(skb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+                              ++vcc->stats->tx_err;
-+#else
-+                              atomic_inc(&vcc->stats->tx_err);
-+#endif
-+                              return -ENOMEM;
-+                      }
-+                      tpd->status |= TPD_USERCELL;
-+                      slot = 0;
-+              }
-+
-+              tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev,
-+                      (void *) page_address(frag->page) + frag->page_offset,
-+                              frag->size, PCI_DMA_TODEVICE);
-+              tpd->iovec[slot].len = frag->size;
-+              ++slot;
-+
-+      }
-+
-+      tpd->iovec[slot-1].len |= TPD_LST;
-+#else
-+      tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
-+      tpd->length0 = skb->len | TPD_LST;
-+#endif
-+      tpd->status |= TPD_INT;
-+
-+      tpd->vcc = vcc;
-+      tpd->skb = skb;
-+      mb();
-+      ATM_SKB(skb)->vcc = vcc;
-+
-+      HE_SPIN_LOCK(he_dev, flags);
-+      he_enqueue_tpd(he_dev, tpd, cid);
-+      HE_SPIN_UNLOCK(he_dev, flags);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
-+      ++vcc->stats->tx;
-+#else
-+      atomic_inc(&vcc->stats->tx);
-+#endif
-+
-+      return 0;
-+}
-+
-+static int
-+he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg)
-+{
-+      unsigned long flags;
-+      struct he_dev *he_dev = HE_DEV(atm_dev);
-+      struct he_ioctl_reg reg;
-+      int err = 0;
-+
-+      switch (cmd)
-+      {
-+              case HE_GET_REG:
-+                      if (!capable(CAP_NET_ADMIN)) return -EPERM;
-+
-+                      copy_from_user(&reg, (struct he_ioctl_reg *) arg,
-+                                              sizeof(struct he_ioctl_reg));
-+                      HE_SPIN_LOCK(he_dev, flags);
-+                      switch (reg.type)
-+                      {
-+                              case HE_REGTYPE_PCI:
-+                                      reg.val = he_readl(he_dev, reg.addr);
-+                                      break;
-+                              case HE_REGTYPE_RCM:
-+                                      reg.val =
-+                                              he_readl_rcm(he_dev, reg.addr);
-+                                      break;
-+                              case HE_REGTYPE_TCM:
-+                                      reg.val =
-+                                              he_readl_tcm(he_dev, reg.addr);
-+                                      break;
-+                              case HE_REGTYPE_MBOX:
-+                                      reg.val =
-+                                              he_readl_mbox(he_dev, reg.addr);
-+                                      break;
-+                              default:
-+                                      HE_SPIN_UNLOCK(he_dev, flags);
-+                                      return -EINVAL;
-+                      }
-+                      HE_SPIN_UNLOCK(he_dev, flags);
-+                      copy_to_user((struct he_ioctl_reg *) arg, &reg,
-+                                              sizeof(struct he_ioctl_reg));
-+                      break;
-+              default:
-+#ifdef CONFIG_ATM_HE_USE_SUNI
-+                      HE_SPIN_LOCK(he_dev, flags);
-+                      if (atm_dev->phy && atm_dev->phy->ioctl)
-+                              err = atm_dev->phy->ioctl(atm_dev, cmd, arg);
-+                      HE_SPIN_UNLOCK(he_dev, flags);
-+#else /* CONFIG_ATM_HE_USE_SUNI */
-+                      return -EINVAL;
-+#endif /* CONFIG_ATM_HE_USE_SUNI */
-+                      break;
-+      }
-+
-+      return err;
-+}
-+
-+static void
-+he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr)
-+{
-+      struct he_dev *he_dev = HE_DEV(atm_dev);
-+
-+      HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr);
-+
-+        he_writel(he_dev, val, FRAMER + (addr*4));
-+}
-+ 
-+        
-+static unsigned char
-+he_phy_get(struct atm_dev *atm_dev, unsigned long addr)
-+{ 
-+      struct he_dev *he_dev = HE_DEV(atm_dev);
-+      unsigned reg;
-+
-+        reg = he_readl(he_dev, FRAMER + (addr*4));
-+
-+      HPRINTK("phy_get(addr 0x%lx) =0x%lx\n", addr, reg);
-+      return reg;
-+}
-+
-+static int
-+he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
-+{
-+      unsigned long flags;
-+      struct he_dev *he_dev = HE_DEV(dev);
-+      int left, i;
-+#ifdef notdef
-+      struct he_rbrq *rbrq_tail;
-+      struct he_tpdrq *tpdrq_head;
-+        int rbpl_head, rbpl_tail;
-+#endif
-+      static long mcc = 0, oec = 0, dcc = 0, cec = 0;
-+
-+
-+      left = *pos;
-+      if (!left--)
-+              return sprintf(page, "%s\n", version);
-+
-+      if (!left--)
-+              return sprintf(page, "%s%s\n\n",
-+                      he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM");
-+
-+      if (!left--)
-+              return sprintf(page, "Mismatched Cells  VPI/VCI Not Open  Dropped Cells  RCM Dropped Cells\n");
-+
-+      HE_SPIN_LOCK(he_dev, flags);
-+      mcc += he_readl(he_dev, MCC);
-+      oec += he_readl(he_dev, OEC);
-+      dcc += he_readl(he_dev, DCC);
-+      cec += he_readl(he_dev, CEC);
-+      HE_SPIN_UNLOCK(he_dev, flags);
-+
-+      if (!left--)
-+              return sprintf(page, "%16ld  %16ld  %13ld  %17ld\n\n", 
-+                                                      mcc, oec, dcc, cec);
-+
-+      if (!left--)
-+              return sprintf(page, "irq_size = %d  inuse = ?  peak = %d\n",
-+                              CONFIG_IRQ_SIZE, he_dev->irq_peak);
-+
-+      if (!left--)
-+              return sprintf(page, "tpdrq_size = %d  inuse = ?\n",
-+                                              CONFIG_TPDRQ_SIZE);
-+
-+      if (!left--)
-+              return sprintf(page, "rbrq_size = %d  inuse = ?  peak = %d\n",
-+                              CONFIG_RBRQ_SIZE, he_dev->rbrq_peak);
-+
-+      if (!left--)
-+              return sprintf(page, "tbrq_size = %d  peak = %d\n",
-+                                      CONFIG_TBRQ_SIZE, he_dev->tbrq_peak);
-+
-+
-+#ifdef notdef
-+        rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S));
-+        rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T));
-+
-+      inuse = rbpl_head - rbpl_tail;
-+      if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp);
-+      inuse /= sizeof(struct he_rbp);
-+
-+      if (!left--)
-+              return sprintf(page, "rbpl_size = %d  inuse = %d\n\n",
-+                                              CONFIG_RBPL_SIZE, inuse);
-+#endif
-+
-+      if (!left--)
-+              return sprintf(page, "rate controller periods (cbr)\n                 pcr  #vc\n");
-+
-+      for (i = 0; i < HE_NUM_CS_STPER; ++i)
-+              if (!left--)
-+                      return sprintf(page, "cs_stper%-2d  %8ld  %3d\n", i,
-+                                              he_dev->cs_stper[i].pcr,
-+                                              he_dev->cs_stper[i].inuse);
-+
-+      if (!left--)
-+              return sprintf(page, "total bw (cbr): %d  (limit %d)\n",
-+                      he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9);
-+
-+      return 0;
-+}
-+
-+/* eeprom routines  -- see 4.7 */
-+
-+u8
-+read_prom_byte(struct he_dev *he_dev, int addr)
-+{
-+      u32 val = 0, tmp_read = 0;
-+      int i, j = 0;
-+      u8 byte_read = 0;
-+
-+      val = readl(he_dev->membase + HOST_CNTL);
-+      val &= 0xFFFFE0FF;
-+       
-+      /* Turn on write enable */
-+      val |= 0x800;
-+      writel(val, he_dev->membase + HOST_CNTL);
-+       
-+      /* Send READ instruction */
-+      for (i=0; i<sizeof(readtab)/sizeof(readtab[0]); i++) {
-+              writel(val | readtab[i], he_dev->membase + HOST_CNTL);
-+              udelay(EEPROM_DELAY);
-+      }
-+       
-+        /* Next, we need to send the byte address to read from */
-+      for (i=7; i>=0; i--) {
-+              writel(val | clocktab[j++] | (((addr >> i) & 1) << 9),
-+                      he_dev->membase + HOST_CNTL);
-+              udelay(EEPROM_DELAY);
-+              writel(val | clocktab[j++] | (((addr >> i) & 1) << 9),
-+                      he_dev->membase + HOST_CNTL);
-+              udelay(EEPROM_DELAY);
-+      }
-+       
-+      j=0;
-+
-+      val &= 0xFFFFF7FF;      /* Turn off write enable */
-+      writel(val, he_dev->membase + HOST_CNTL);
-+       
-+      /* Now, we can read data from the EEPROM by clocking it in */
-+      for (i=7; i>=0; i--) {
-+              writel(val | clocktab[j++], he_dev->membase + HOST_CNTL);
-+              udelay(EEPROM_DELAY);
-+              tmp_read = readl(he_dev->membase + HOST_CNTL);
-+              byte_read |= (unsigned char)
-+                              ((tmp_read & ID_DOUT)
-+                               >> ID_DOFFSET << i);
-+              writel(val | clocktab[j++],
-+              he_dev->membase + HOST_CNTL);
-+              udelay(EEPROM_DELAY);
-+      }
-+       
-+      writel(val | clocktab[j++], he_dev->membase + HOST_CNTL);
-+      udelay(EEPROM_DELAY);
-+
-+        return (byte_read);
-+}
-+
-+MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
-+MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver");
-+MODULE_PARM(disable64, "h");
-+MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers");
-+MODULE_PARM(nvpibits, "i");
-+MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)");
-+MODULE_PARM(nvcibits, "i");
-+MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)");
-+MODULE_PARM(rx_skb_reserve, "i");
-+MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)");
-+MODULE_PARM(irq_coalesce, "i");
-+MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
-+MODULE_PARM(sdh, "i");
-+MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
-+static struct pci_device_id he_pci_tbl[] __devinitdata = {
-+      { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID,
-+        0, 0, 0 },
-+        { 0, }
-+};
-+
-+static struct pci_driver he_driver = {
-+      .name =         "he",
-+      .probe =        he_init_one,
-+      .remove =       __devexit_p(he_remove_one),
-+      .id_table =     he_pci_tbl,
-+};
-+
-+static int __init he_init(void)
-+{
-+        return pci_module_init(&he_driver);
-+}
-+
-+static void __exit he_cleanup(void)
-+{
-+        pci_unregister_driver(&he_driver);
-+}
-+
-+module_init(he_init);
-+module_exit(he_cleanup);
-+#else
-+static int __init
-+he_init()
-+{
-+      if (!pci_present())
-+              return -EIO;
-+
-+#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
-+      /* request_module("suni"); */
-+#endif
-+
-+      pci_dev = NULL;
-+      while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FORE,
-+                                      PCI_DEVICE_ID_FORE_HE, pci_dev)) != NULL)
-+              if (he_init_one(pci_dev, NULL) == 0)
-+                      ++ndevs;
-+
-+      return (ndevs ? 0 : -ENODEV);
-+}
-+
-+static void __devexit
-+he_cleanup(void)
-+{
-+      while (he_devs)
-+      {
-+              struct he_dev *next = he_devs->next;
-+              he_stop(he_devs);
-+              atm_dev_deregister(he_devs->atm_dev);
-+              kfree(he_devs);
-+
-+              he_devs = next;
-+      }
-+
-+}
-+
-+int init_module(void)
-+{
-+      return he_init();
-+}
-+
-+void cleanup_module(void)
-+{
-+      he_cleanup();
-+}
-+#endif
-+
-+MODULE_LICENSE("GPL");
-diff -urN linux-2.4.20/drivers/atm/he.h linux-2.4.20-atm/drivers/atm/he.h
---- linux-2.4.20/drivers/atm/he.h      Thu Jan  1 01:00:00 1970
-+++ linux-2.4.20-atm/drivers/atm/he.h  Wed May 28 01:58:41 2003
-@@ -0,0 +1,910 @@
-+/* $Id$ */
-+
-+/*
-+
-+  he.h
-+
-+  ForeRunnerHE ATM Adapter driver for ATM on Linux
-+  Copyright (C) 1999-2001  Naval Research Laboratory
-+
-+  This library is free software; you can redistribute it and/or
-+  modify it under the terms of the GNU Lesser General Public
-+  License as published by the Free Software Foundation; either
-+  version 2.1 of the License, or (at your option) any later version.
-+
-+  This library is distributed in the hope that it will be useful,
-+  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+  Lesser General Public License for more details.
-+
-+  You should have received a copy of the GNU Lesser General Public
-+  License along with this library; if not, write to the Free Software
-+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+
-+*/
-+
-+/*
-+
-+  he.h
-+
-+  ForeRunnerHE ATM Adapter driver for ATM on Linux
-+  Copyright (C) 1999-2000  Naval Research Laboratory
-+
-+  Permission to use, copy, modify and distribute this software and its
-+  documentation is hereby granted, provided that both the copyright
-+  notice and this permission notice appear in all copies of the software,
-+  derivative works or modified versions, and any portions thereof, and
-+  that both notices appear in supporting documentation.
-+
-+  NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
-+  DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
-+  RESULTING FROM THE USE OF THIS SOFTWARE.
-+
-+ */
-+
-+#ifndef _HE_H_
-+#define _HE_H_
-+
-+#define DEV_LABEL       "he"
-+
-+#define CONFIG_DEFAULT_VCIBITS        12
-+#define CONFIG_DEFAULT_VPIBITS        0
-+
-+#define CONFIG_IRQ_SIZE               128
-+#define CONFIG_IRQ_THRESH     (CONFIG_IRQ_SIZE/2)
-+
-+#define CONFIG_TPDRQ_SIZE     512
-+#define TPDRQ_MASK(x)         (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1))
-+
-+#define CONFIG_RBRQ_SIZE      512
-+#define CONFIG_RBRQ_THRESH    400
-+#define RBRQ_MASK(x)          (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1))
-+
-+#define CONFIG_TBRQ_SIZE      512
-+#define CONFIG_TBRQ_THRESH    400
-+#define TBRQ_MASK(x)          (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1))
-+
-+#define CONFIG_RBPL_SIZE      512
-+#define CONFIG_RBPL_THRESH    64
-+#define CONFIG_RBPL_BUFSIZE   4096
-+#define RBPL_MASK(x)          (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1))
-+
-+#define CONFIG_RBPS_SIZE      1024
-+#define CONFIG_RBPS_THRESH    64
-+#define CONFIG_RBPS_BUFSIZE   128
-+#define RBPS_MASK(x)          (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1))
-+
-+/* 5.1.3 initialize connection memory */
-+
-+#define CONFIG_RSRA           0x00000
-+#define CONFIG_RCMLBM         0x08000
-+#define CONFIG_RCMABR         0x0d800
-+#define CONFIG_RSRB           0x0e000
-+
-+#define CONFIG_TSRA           0x00000
-+#define CONFIG_TSRB           0x08000
-+#define CONFIG_TSRC           0x0c000
-+#define CONFIG_TSRD           0x0e000
-+#define CONFIG_TMABR          0x0f000
-+#define CONFIG_TPDBA          0x10000
-+
-+#define HE_MAXCIDBITS         12
-+
-+/* 2.9.3.3 interrupt encodings */
-+
-+struct he_irq {
-+      volatile u32 isw;
-+};
-+
-+#define IRQ_ALIGNMENT         0x1000
-+
-+#define NEXT_ENTRY(base, tail, mask) \
-+                              (((unsigned long)base)|(((unsigned long)(tail+1))&mask))
-+
-+#define ITYPE_INVALID         0xffffffff
-+#define ITYPE_TBRQ_THRESH     (0<<3)
-+#define ITYPE_TPD_COMPLETE    (1<<3)
-+#define ITYPE_RBPS_THRESH     (2<<3)
-+#define ITYPE_RBPL_THRESH     (3<<3)
-+#define ITYPE_RBRQ_THRESH     (4<<3)
-+#define ITYPE_RBRQ_TIMER      (5<<3)
-+#define ITYPE_PHY             (6<<3)
-+#define ITYPE_OTHER           0x80
-+#define ITYPE_PARITY          0x81
-+#define ITYPE_ABORT           0x82
-+
-+#define ITYPE_GROUP(x)                (x & 0x7)
-+#define ITYPE_TYPE(x)         (x & 0xf8)
-+
-+#define HE_NUM_GROUPS 8
-+
-+/* 2.1.4 transmit packet descriptor */
-+
-+struct he_tpd {
-+
-+      /* read by the adapter */
-+
-+      volatile u32 status;
-+      volatile u32 reserved;
-+
-+#define TPD_MAXIOV    3
-+      struct {
-+              u32 addr, len;
-+      } iovec[TPD_MAXIOV];
-+
-+
-+#define address0 iovec[0].addr
-+#define length0 iovec[0].len
-+
-+      /* linux-atm extensions */
-+
-+      struct sk_buff *skb;
-+      struct atm_vcc *vcc;
-+
-+      struct list_head entry;
-+};
-+
-+#define TPD_ALIGNMENT 64
-+#define TPD_LEN_MASK  0xffff
-+
-+#define TPD_ADDR(x)   ((x) & 0xffffffc0)
-+
-+
-+/* table 2.3 transmit buffer return elements */
-+
-+struct he_tbrq {
-+      volatile u32 tbre;
-+};
-+
-+#define TBRQ_ALIGNMENT        CONFIG_TBRQ_SIZE
-+
-+#define TBRQ_TPD(tbrq)                ((tbrq)->tbre & 0xffffffc0)
-+#define TBRQ_EOS(tbrq)                ((tbrq)->tbre & (1<<3))
-+#define TBRQ_MULTIPLE(tbrq)   ((tbrq)->tbre & (1))
-+
-+/* table 2.21 receive buffer return queue element field organization */
-+
-+struct he_rbrq {
-+      volatile u32 addr;
-+      volatile u32 cidlen;
-+};
-+
-+#define RBRQ_ALIGNMENT        CONFIG_RBRQ_SIZE
-+
-+#define RBRQ_ADDR(rbrq)               ((rbrq)->addr & 0xffffffc0)
-+#define RBRQ_CRC_ERR(rbrq)    ((rbrq)->addr & (1<<5))
-+#define RBRQ_LEN_ERR(rbrq)    ((rbrq)->addr & (1<<4))
-+#define RBRQ_END_PDU(rbrq)    ((rbrq)->addr & (1<<3))
-+#define RBRQ_AAL5_PROT(rbrq)  ((rbrq)->addr & (1<<2))
-+#define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1))
-+#define RBRQ_HBUF_ERR(rbrq)   ((rbrq)->addr & 1)
-+#define RBRQ_CID(rbrq)                (((rbrq)->cidlen >> 16) & 0x1fff)
-+#define RBRQ_BUFLEN(rbrq)     ((rbrq)->cidlen & 0xffff)
-+
-+/* figure 2.3 transmit packet descriptor ready queue */
-+
-+struct he_tpdrq {
-+      volatile u32 tpd;
-+      volatile u32 cid;
-+};
-+
-+#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE
-+
-+/* table 2.30 host status page detail */
-+
-+#define HSP_ALIGNMENT 0x400           /* must align on 1k boundary */
-+
-+struct he_hsp {
-+      struct he_hsp_entry {
-+              volatile u32 tbrq_tail; 
-+              volatile u32 reserved1[15];
-+              volatile u32 rbrq_tail; 
-+              volatile u32 reserved2[15];
-+      } group[HE_NUM_GROUPS];
-+};
-+
-+/* figure 2.9 receive buffer pools */
-+
-+struct he_rbp {
-+      volatile u32 phys;
-+      volatile u32 status;
-+};
-+
-+/* NOTE: it is suggested that virt be the virtual address of the host
-+   buffer.  on a 64-bit machine, this would not work.  Instead, we
-+   store the real virtual address in another list, and store an index
-+   (and buffer status) in the virt member.
-+*/
-+
-+#define RBP_INDEX_OFF 6
-+#define RBP_INDEX(x)  (((long)(x) >> RBP_INDEX_OFF) & 0xffff)
-+#define RBP_LOANED    0x80000000
-+#define RBP_SMALLBUF  0x40000000
-+
-+struct he_virt {
-+      void *virt;
-+};
-+
-+#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE
-+#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE
-+
-+#ifdef notyet
-+struct he_group {
-+      u32 rpbs_size, rpbs_qsize;
-+      struct he_rbp rbps_ba;
-+
-+      u32 rpbl_size, rpbl_qsize;
-+      struct he_rpb_entry *rbpl_ba;
-+};
-+#endif
-+
-+#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc)
-+
-+struct he_vcc_table 
-+{
-+      struct atm_vcc *vcc;
-+};
-+
-+struct he_cs_stper
-+{
-+      long pcr;
-+      int inuse;
-+};
-+
-+#define HE_NUM_CS_STPER               16
-+
-+struct he_dev {
-+      unsigned int number;
-+      unsigned int irq;
-+      unsigned long membase;
-+
-+      char prod_id[30];
-+      char mac_addr[6];
-+      int media;                      /*  
-+                                       *  0x26 = HE155 MM 
-+                                       *  0x27 = HE622 MM 
-+                                       *  0x46 = HE155 SM 
-+                                       *  0x47 = HE622 SM 
-+                                       */
-+
-+
-+      unsigned int vcibits, vpibits;
-+      unsigned int cells_per_row;
-+      unsigned int bytes_per_row;
-+      unsigned int cells_per_lbuf;
-+      unsigned int r0_numrows, r0_startrow, r0_numbuffs;
-+      unsigned int r1_numrows, r1_startrow, r1_numbuffs;
-+      unsigned int tx_numrows, tx_startrow, tx_numbuffs;
-+      unsigned int buffer_limit;
-+
-+      struct he_vcc_table *he_vcc_table;
-+
-+#ifdef notyet
-+      struct he_group group[HE_NUM_GROUPS];
-+#endif
-+      struct he_cs_stper cs_stper[HE_NUM_CS_STPER];
-+      unsigned total_bw;
-+
-+      dma_addr_t irq_phys;
-+      struct he_irq *irq_base, *irq_head, *irq_tail;
-+      volatile unsigned *irq_tailoffset;
-+      int irq_peak;
-+
-+#ifdef USE_TASKLET
-+      struct tasklet_struct tasklet;
-+#endif
-+
-+      struct pci_pool *tpd_pool;
-+      struct list_head outstanding_tpds;
-+      dma_addr_t tpdrq_phys;
-+      struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head;
-+      spinlock_t tpdrq_lock;  /* serialize access to tpdrq */
-+
-+      spinlock_t global_lock;         /* 8.1.5 pci transaction ordering
-+                                        error problem */
-+      dma_addr_t rbrq_phys;
-+      struct he_rbrq *rbrq_base, *rbrq_head;
-+      int rbrq_peak;
-+
-+      struct pci_pool *rbpl_pool;
-+      dma_addr_t rbpl_phys;
-+      struct he_rbp *rbpl_base, *rbpl_tail;
-+      struct he_virt *rbpl_virt;
-+      int rbpl_peak;
-+
-+      struct pci_pool *rbps_pool;
-+      dma_addr_t rbps_phys;
-+      struct he_rbp *rbps_base, *rbps_tail;
-+      struct he_virt *rbps_virt;
-+      int rbps_peak;
-+
-+      dma_addr_t tbrq_phys;
-+      struct he_tbrq *tbrq_base, *tbrq_head;
-+      int tbrq_peak;
-+
-+      dma_addr_t hsp_phys;
-+      struct he_hsp *hsp;
-+
-+      struct pci_dev *pci_dev;
-+      struct atm_dev *atm_dev;
-+      struct he_dev *next;
-+};
-+
-+struct he_vcc
-+{
-+      struct iovec iov_head[32];
-+      struct iovec *iov_tail;
-+      int pdu_len;
-+
-+      int rc_index;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-+      struct wait_queue *rx_waitq;
-+      atruct wait_queue *tx_waitq;
-+#else
-+      wait_queue_head_t rx_waitq;
-+      wait_queue_head_t tx_waitq;
-+#endif
-+};
-+
-+#define HE_VCC(vcc)   ((struct he_vcc *)(vcc->dev_data))
-+
-+#define PCI_VENDOR_ID_FORE    0x1127
-+#define PCI_DEVICE_ID_FORE_HE 0x400
-+
-+#define HE_DMA_MASK           0xffffffff
-+
-+#define GEN_CNTL_0                            0x40
-+#define  INT_PROC_ENBL                (1<<25)
-+#define  SLAVE_ENDIAN_MODE    (1<<16)
-+#define  MRL_ENB              (1<<5)
-+#define  MRM_ENB              (1<<4)
-+#define  INIT_ENB             (1<<2)
-+#define  IGNORE_TIMEOUT               (1<<1)
-+#define  ENBL_64              (1<<0)
-+
-+#define MIN_PCI_LATENCY               32      /* errata 8.1.3 */
-+
-+#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data)
-+
-+#define he_is622(dev) ((dev)->media & 0x1)
-+
-+#define HE_REGMAP_SIZE        0x100000
-+
-+#define RESET_CNTL    0x80000
-+#define  BOARD_RST_STATUS     (1<<6)
-+
-+#define HOST_CNTL     0x80004
-+#define  PCI_BUS_SIZE64                       (1<<27)
-+#define  DESC_RD_STATIC_64            (1<<26)
-+#define  DATA_RD_STATIC_64            (1<<25)
-+#define  DATA_WR_STATIC_64            (1<<24)
-+#define  ID_CS                                (1<<12)
-+#define  ID_WREN                      (1<<11)
-+#define  ID_DOUT                      (1<<10)
-+#define   ID_DOFFSET                  10
-+#define  ID_DIN                               (1<<9)
-+#define  ID_CLOCK                     (1<<8)
-+#define  QUICK_RD_RETRY                       (1<<7)
-+#define  QUICK_WR_RETRY                       (1<<6)
-+#define  OUTFF_ENB                    (1<<5)
-+#define  CMDFF_ENB                    (1<<4)
-+#define  PERR_INT_ENB                 (1<<2)
-+#define  IGNORE_INTR                  (1<<0)
-+
-+#define LB_SWAP               0x80008
-+#define  SWAP_RNUM_MAX(x)     (x<<27)
-+#define  DATA_WR_SWAP         (1<<20)
-+#define  DESC_RD_SWAP         (1<<19)
-+#define  DATA_RD_SWAP         (1<<18)
-+#define  INTR_SWAP            (1<<17)
-+#define  DESC_WR_SWAP         (1<<16)
-+#define  SDRAM_INIT           (1<<15)
-+#define  BIG_ENDIAN_HOST      (1<<14)
-+#define  XFER_SIZE            (1<<7)
-+
-+#define LB_MEM_ADDR   0x8000c
-+#define LB_MEM_DATA   0x80010
-+
-+#define LB_MEM_ACCESS 0x80014
-+#define  LB_MEM_HNDSHK                (1<<30)
-+#define  LM_MEM_WRITE         (0x7)
-+#define  LM_MEM_READ          (0x3)
-+
-+#define SDRAM_CTL     0x80018
-+#define  LB_64_ENB            (1<<3)
-+#define  LB_TWR                       (1<<2)
-+#define  LB_TRP                       (1<<1)
-+#define  LB_TRAS              (1<<0)
-+
-+#define INT_FIFO      0x8001c
-+#define  INT_MASK_D           (1<<15)
-+#define  INT_MASK_C           (1<<14)
-+#define  INT_MASK_B           (1<<13)
-+#define  INT_MASK_A           (1<<12)
-+#define  INT_CLEAR_D          (1<<11)
-+#define  INT_CLEAR_C          (1<<10)
-+#define  INT_CLEAR_B          (1<<9)
-+#define  INT_CLEAR_A          (1<<8)
-+
-+#define ABORT_ADDR    0x80020
-+
-+#define IRQ0_BASE     0x80080
-+#define  IRQ_BASE(x)          (x<<12)
-+#define  IRQ_MASK             ((CONFIG_IRQ_SIZE<<2)-1)        /* was 0x3ff */
-+#define  IRQ_TAIL(x)          (((unsigned long)(x)) & IRQ_MASK)
-+#define IRQ0_HEAD     0x80084
-+#define  IRQ_SIZE(x)          (x<<22)
-+#define  IRQ_THRESH(x)                (x<<12)
-+#define  IRQ_HEAD(x)          (x<<2)
-+/* #define  IRQ_PENDING               (1)             conflict with linux/irq.h */
-+#define IRQ0_CNTL     0x80088
-+#define  IRQ_ADDRSEL(x)               (x<<2)
-+#define  IRQ_INT_A            (0<<2)
-+#define  IRQ_INT_B            (1<<2)
-+#define  IRQ_INT_C            (2<<2)
-+#define  IRQ_INT_D            (3<<2)
-+#define  IRQ_TYPE_ADDR                0x1
-+#define  IRQ_TYPE_LINE                0x0
-+#define IRQ0_DATA     0x8008c
-+
-+#define IRQ1_BASE     0x80090
-+#define IRQ1_HEAD     0x80094
-+#define IRQ1_CNTL     0x80098
-+#define IRQ1_DATA     0x8009c
-+
-+#define IRQ2_BASE     0x800a0
-+#define IRQ2_HEAD     0x800a4
-+#define IRQ2_CNTL     0x800a8
-+#define IRQ2_DATA     0x800ac
-+
-+#define IRQ3_BASE     0x800b0
-+#define IRQ3_HEAD     0x800b4
-+#define IRQ3_CNTL     0x800b8
-+#define IRQ3_DATA     0x800bc
-+
-+#define GRP_10_MAP    0x800c0
-+#define GRP_32_MAP    0x800c4
-+#define GRP_54_MAP    0x800c8
-+#define GRP_76_MAP    0x800cc
-+
-+#define       G0_RBPS_S       0x80400
-+#define G0_RBPS_T     0x80404
-+#define  RBP_TAIL(x)          ((x)<<3)
-+#define  RBP_MASK(x)          ((x)|0x1fff)
-+#define G0_RBPS_QI    0x80408
-+#define  RBP_QSIZE(x)         ((x)<<14)
-+#define  RBP_INT_ENB          (1<<13)
-+#define  RBP_THRESH(x)                (x)
-+#define G0_RBPS_BS    0x8040c
-+#define G0_RBPL_S     0x80410
-+#define G0_RBPL_T     0x80414
-+#define G0_RBPL_QI    0x80418 
-+#define G0_RBPL_BS    0x8041c
-+
-+#define       G1_RBPS_S       0x80420
-+#define G1_RBPS_T     0x80424
-+#define G1_RBPS_QI    0x80428
-+#define G1_RBPS_BS    0x8042c
-+#define G1_RBPL_S     0x80430
-+#define G1_RBPL_T     0x80434
-+#define G1_RBPL_QI    0x80438
-+#define G1_RBPL_BS    0x8043c
-+
-+#define       G2_RBPS_S       0x80440
-+#define G2_RBPS_T     0x80444
-+#define G2_RBPS_QI    0x80448
-+#define G2_RBPS_BS    0x8044c
-+#define G2_RBPL_S     0x80450
-+#define G2_RBPL_T     0x80454
-+#define G2_RBPL_QI    0x80458
-+#define G2_RBPL_BS    0x8045c
-+
-+#define       G3_RBPS_S       0x80460
-+#define G3_RBPS_T     0x80464
-+#define G3_RBPS_QI    0x80468
-+#define G3_RBPS_BS    0x8046c
-+#define G3_RBPL_S     0x80470
-+#define G3_RBPL_T     0x80474
-+#define G3_RBPL_QI    0x80478
-+#define G3_RBPL_BS    0x8047c
-+
-+#define       G4_RBPS_S       0x80480
-+#define G4_RBPS_T     0x80484
-+#define G4_RBPS_QI    0x80488
-+#define G4_RBPS_BS    0x8048c
-+#define G4_RBPL_S     0x80490
-+#define G4_RBPL_T     0x80494
-+#define G4_RBPL_QI    0x80498
-+#define G4_RBPL_BS    0x8049c
-+
-+#define       G5_RBPS_S       0x804a0
-+#define G5_RBPS_T     0x804a4
-+#define G5_RBPS_QI    0x804a8
-+#define G5_RBPS_BS    0x804ac
-+#define G5_RBPL_S     0x804b0
-+#define G5_RBPL_T     0x804b4
-+#define G5_RBPL_QI    0x804b8
-+#define G5_RBPL_BS    0x804bc
-+
-+#define       G6_RBPS_S       0x804c0
-+#define G6_RBPS_T     0x804c4
-+#define G6_RBPS_QI    0x804c8
-+#define G6_RBPS_BS    0x804cc
-+#define G6_RBPL_S     0x804d0
-+#define G6_RBPL_T     0x804d4
-+#define G6_RBPL_QI    0x804d8
-+#define G6_RBPL_BS    0x804dc
-+
-+#define       G7_RBPS_S       0x804e0
-+#define G7_RBPS_T     0x804e4
-+#define G7_RBPS_QI    0x804e8
-+#define G7_RBPS_BS    0x804ec
-+
-+#define G7_RBPL_S     0x804f0
-+#define G7_RBPL_T     0x804f4
-+#define G7_RBPL_QI    0x804f8
-+#define G7_RBPL_BS    0x804fc
-+
-+#define G0_RBRQ_ST    0x80500
-+#define G0_RBRQ_H     0x80504
-+#define G0_RBRQ_Q     0x80508
-+#define  RBRQ_THRESH(x)               ((x)<<13)
-+#define  RBRQ_SIZE(x)         (x)
-+#define G0_RBRQ_I     0x8050c
-+#define  RBRQ_TIME(x)         ((x)<<8)
-+#define  RBRQ_COUNT(x)                (x)
-+
-+/* fill in 1 ... 7 later */
-+
-+#define G0_TBRQ_B_T   0x80600
-+#define G0_TBRQ_H     0x80604
-+#define G0_TBRQ_S     0x80608
-+#define G0_TBRQ_THRESH        0x8060c
-+#define  TBRQ_THRESH(x)               (x)
-+
-+/* fill in 1 ... 7 later */
-+
-+#define RH_CONFIG     0x805c0
-+#define  PHY_INT_ENB  (1<<10)
-+#define  OAM_GID(x)   (x<<7)
-+#define  PTMR_PRE(x)  (x)
-+
-+#define G0_INMQ_S     0x80580
-+#define G0_INMQ_L     0x80584
-+#define G1_INMQ_S     0x80588
-+#define G1_INMQ_L     0x8058c
-+#define G2_INMQ_S     0x80590
-+#define G2_INMQ_L     0x80594
-+#define G3_INMQ_S     0x80598
-+#define G3_INMQ_L     0x8059c
-+#define G4_INMQ_S     0x805a0
-+#define G4_INMQ_L     0x805a4
-+#define G5_INMQ_S     0x805a8
-+#define G5_INMQ_L     0x805ac
-+#define G6_INMQ_S     0x805b0
-+#define G6_INMQ_L     0x805b4
-+#define G7_INMQ_S     0x805b8
-+#define G7_INMQ_L     0x805bc
-+
-+#define TPDRQ_B_H     0x80680
-+#define TPDRQ_T               0x80684
-+#define TPDRQ_S               0x80688
-+
-+#define UBUFF_BA      0x8068c
-+
-+#define RLBF0_H               0x806c0
-+#define RLBF0_T               0x806c4
-+#define RLBF1_H               0x806c8
-+#define RLBF1_T               0x806cc
-+#define RLBC_H                0x806d0
-+#define RLBC_T                0x806d4
-+#define RLBC_H2               0x806d8
-+#define TLBF_H                0x806e0
-+#define TLBF_T                0x806e4
-+#define RLBF0_C               0x806e8
-+#define RLBF1_C               0x806ec
-+#define RXTHRSH               0x806f0
-+#define LITHRSH               0x806f4
-+
-+#define LBARB         0x80700
-+#define  SLICE_X(x)            (x<<28)
-+#define  ARB_RNUM_MAX(x)       (x<<23)
-+#define  TH_PRTY(x)            (x<<21)
-+#define  RH_PRTY(x)            (x<<19)
-+#define  TL_PRTY(x)            (x<<17)
-+#define  RL_PRTY(x)            (x<<15)
-+#define  BUS_MULTI(x)          (x<<8)
-+#define  NET_PREF(x)           (x)
-+
-+#define SDRAMCON      0x80704
-+#define        BANK_ON                (1<<14)
-+#define        WIDE_DATA              (1<<13)
-+#define        TWR_WAIT               (1<<12)
-+#define        TRP_WAIT               (1<<11)
-+#define        TRAS_WAIT              (1<<10)
-+#define        REF_RATE(x)            (x)
-+
-+#define LBSTAT                0x80708
-+
-+#define RCC_STAT      0x8070c
-+#define  RCC_BUSY             (1)
-+
-+#define TCMCONFIG     0x80740
-+#define  TM_DESL2             (1<<10)
-+#define        TM_BANK_WAIT(x)        (x<<6)
-+#define        TM_ADD_BANK4(x)        (x<<4)
-+#define  TM_PAR_CHECK(x)      (x<<3)
-+#define  TM_RW_WAIT(x)                (x<<2)
-+#define  TM_SRAM_TYPE(x)      (x)
-+
-+#define TSRB_BA               0x80744 
-+#define TSRC_BA               0x80748 
-+#define TMABR_BA      0x8074c 
-+#define TPD_BA                0x80750 
-+#define TSRD_BA               0x80758 
-+
-+#define TX_CONFIG     0x80760
-+#define  DRF_THRESH(x)                (x<<22)
-+#define  TX_UT_MODE(x)                (x<<21)
-+#define  TX_VCI_MASK(x)               (x<<17)
-+#define  LBFREE_CNT(x)                (x)
-+
-+#define TXAAL5_PROTO  0x80764
-+#define  CPCS_UU(x)           (x<<8)
-+#define  CPI(x)                       (x)
-+
-+#define RCMCONFIG     0x80780
-+#define  RM_DESL2(x)          (x<<10)
-+#define  RM_BANK_WAIT(x)      (x<<6)
-+#define  RM_ADD_BANK(x)               (x<<4)
-+#define  RM_PAR_CHECK(x)      (x<<3)
-+#define  RM_RW_WAIT(x)                (x<<2)
-+#define  RM_SRAM_TYPE(x)      (x)
-+
-+#define RCMRSRB_BA    0x80784
-+#define RCMLBM_BA     0x80788
-+#define RCMABR_BA     0x8078c
-+
-+#define RC_CONFIG     0x807c0
-+#define  UT_RD_DELAY(x)               (x<<11)
-+#define  WRAP_MODE(x)         (x<<10)
-+#define  RC_UT_MODE(x)                (x<<9)
-+#define  RX_ENABLE            (1<<8)
-+#define  RX_VALVP(x)          (x<<4)
-+#define  RX_VALVC(x)          (x)
-+
-+#define MCC           0x807c4
-+#define OEC           0x807c8
-+#define DCC           0x807cc
-+#define CEC           0x807d0
-+
-+#define HSP_BA                0x807f0
-+
-+#define LB_CONFIG     0x807f4
-+#define  LB_SIZE(x)           (x)
-+
-+#define CON_DAT               0x807f8
-+#define CON_CTL               0x807fc
-+#define  CON_CTL_MBOX         (2<<30)
-+#define  CON_CTL_TCM          (1<<30)
-+#define  CON_CTL_RCM          (0<<30)
-+#define  CON_CTL_WRITE                (1<<29)
-+#define  CON_CTL_READ         (0<<29)
-+#define  CON_CTL_BUSY         (1<<28)
-+#define  CON_BYTE_DISABLE_3   (1<<22)         /* 24..31 */
-+#define  CON_BYTE_DISABLE_2   (1<<21)         /* 16..23 */
-+#define  CON_BYTE_DISABLE_1   (1<<20)         /* 8..15 */
-+#define  CON_BYTE_DISABLE_0   (1<<19)         /* 0..7 */
-+#define  CON_CTL_ADDR(x)      (x)
-+
-+#define FRAMER                0x80800         /* to 0x80bfc */
-+
-+/* 3.3 network controller (internal) mailbox registers */
-+
-+#define CS_STPER0     0x0
-+      /* ... */
-+#define CS_STPER31    0x01f
-+
-+#define CS_STTIM0     0x020
-+      /* ... */
-+#define CS_STTIM31    0x03f
-+
-+#define CS_TGRLD0     0x040
-+      /* ... */
-+#define CS_TGRLD15    0x04f
-+
-+#define CS_ERTHR0     0x050
-+#define CS_ERTHR1     0x051
-+#define CS_ERTHR2     0x052
-+#define CS_ERTHR3     0x053
-+#define CS_ERTHR4     0x054
-+#define CS_ERCTL0     0x055
-+#define  TX_ENABLE            (1<<28)
-+#define  ER_ENABLE            (1<<27)
-+#define CS_ERCTL1     0x056
-+#define CS_ERCTL2     0x057
-+#define CS_ERSTAT0    0x058
-+#define CS_ERSTAT1    0x059
-+
-+#define CS_RTCCT      0x060
-+#define CS_RTFWC      0x061
-+#define CS_RTFWR      0x062
-+#define CS_RTFTC      0x063
-+#define CS_RTATR      0x064
-+
-+#define CS_TFBSET     0x070
-+#define CS_TFBADD     0x071
-+#define CS_TFBSUB     0x072
-+#define CS_WCRMAX     0x073
-+#define CS_WCRMIN     0x074
-+#define CS_WCRINC     0x075
-+#define CS_WCRDEC     0x076
-+#define CS_WCRCEIL    0x077
-+#define CS_BWDCNT     0x078
-+
-+#define CS_OTPPER     0x080
-+#define CS_OTWPER     0x081
-+#define CS_OTTLIM     0x082
-+#define CS_OTTCNT     0x083
-+
-+#define CS_HGRRT0     0x090
-+      /* ... */
-+#define CS_HGRRT7     0x097
-+
-+#define CS_ORPTRS     0x0a0
-+
-+#define RXCON_CLOSE   0x100
-+
-+
-+#define RCM_MEM_SIZE  0x10000         /* 1M of 32-bit registers */
-+#define TCM_MEM_SIZE  0x20000         /* 2M of 32-bit registers */
-+
-+/* 2.5 transmit connection memory registers */
-+
-+#define TSR0_CONN_STATE(x)    ((x>>28) & 0x7)
-+#define TSR0_USE_WMIN         (1<<23)
-+#define TSR0_GROUP(x)         ((x & 0x7)<<18)
-+#define TSR0_ABR              (2<<16)
-+#define TSR0_UBR              (1<<16)
-+#define TSR0_CBR              (0<<16)
-+#define TSR0_PROT             (1<<15)
-+#define TSR0_AAL0_SDU         (2<<12)
-+#define TSR0_AAL0             (1<<12)
-+#define TSR0_AAL5             (0<<12)
-+#define TSR0_HALT_ER          (1<<11)
-+#define TSR0_MARK_CI          (1<<10)
-+#define TSR0_MARK_ER          (1<<9)
-+#define TSR0_UPDATE_GER               (1<<8)
-+#define TSR0_RC_INDEX(x)      (x & 0x1F)
-+
-+#define TSR1_PCR(x)           ((x & 0x7FFF)<<16)
-+#define TSR1_MCR(x)           (x & 0x7FFF)
-+
-+#define TSR2_ACR(x)           ((x & 0x7FFF)<<16)
-+
-+#define TSR3_NRM_CNT(x)               ((x & 0xFF)<<24)
-+#define TSR3_CRM_CNT(x)               (x & 0xFFFF)
-+
-+#define TSR4_FLUSH_CONN               (1<<31)
-+#define TSR4_SESSION_ENDED    (1<<30)
-+#define TSR4_CRC10            (1<<28)
-+#define TSR4_NULL_CRC10               (1<<27)
-+#define TSR4_PROT             (1<<26)
-+#define TSR4_AAL0_SDU         (2<<23)
-+#define TSR4_AAL0             (1<<23)
-+#define TSR4_AAL5             (0<<23)
-+
-+#define TSR9_OPEN_CONN                (1<<20)
-+
-+#define TSR11_ICR(x)          ((x & 0x7FFF)<<16)
-+#define TSR11_TRM(x)          ((x & 0x7)<<13)
-+#define TSR11_NRM(x)          ((x & 0x7)<<10)
-+#define TSR11_ADTF(x)         (x & 0x3FF)
-+
-+#define TSR13_RDF(x)          ((x & 0xF)<<23)
-+#define TSR13_RIF(x)          ((x & 0xF)<<19)
-+#define TSR13_CDF(x)          ((x & 0x7)<<16)
-+#define TSR13_CRM(x)          (x & 0xFFFF)
-+
-+#define TSR14_DELETE          (1<<31)
-+#define TSR14_ABR_CLOSE               (1<<16)
-+
-+/* 2.7.1 per connection receieve state registers */
-+
-+#define RSR0_START_PDU        (1<<10)
-+#define RSR0_OPEN_CONN        (1<<6)
-+#define RSR0_CLOSE_CONN       (0<<6)
-+#define RSR0_PPD_ENABLE       (1<<5)
-+#define RSR0_EPD_ENABLE       (1<<4)
-+#define RSR0_TCP_CKSUM        (1<<3)
-+#define RSR0_AAL5             (0)
-+#define RSR0_AAL0             (1)
-+#define RSR0_AAL0_SDU         (2)
-+#define RSR0_RAWCELL          (3)
-+#define RSR0_RAWCELL_CRC10    (4)
-+
-+#define RSR1_AQI_ENABLE       (1<<20)
-+#define RSR1_RBPL_ONLY        (1<<19)
-+#define RSR1_GROUP(x) ((x)<<16)
-+
-+#define RSR4_AQI_ENABLE (1<<30)
-+#define RSR4_GROUP(x) ((x)<<27)
-+#define RSR4_RBPL_ONLY        (1<<26)
-+
-+/* 2.1.4 transmit packet descriptor */
-+
-+#define       TPD_USERCELL            0x0
-+#define       TPD_SEGMENT_OAMF5       0x4
-+#define       TPD_END2END_OAMF5       0x5
-+#define       TPD_RMCELL              0x6
-+#define TPD_CELLTYPE(x)               (x<<3)
-+#define TPD_EOS                       (1<<2)
-+#define TPD_CLP                       (1<<1)
-+#define TPD_INT                       (1)
-+#define TPD_LST               (1<<31)
-+
-+/* table 4.3 serial eeprom information */
-+
-+#define PROD_ID               0x08    /* char[] */
-+#define  PROD_ID_LEN  30
-+#define HW_REV                0x26    /* char[] */
-+#define M_SN          0x3a    /* integer */
-+#define MEDIA         0x3e    /* integer */
-+#define  HE155MM      0x26
-+#define  HE155SM      0x27
-+#define  HE622MM      0x46
-+#define  HE622SM      0x47
-+#define MAC_ADDR      0x42    /* char[] */
-+
-+#define CS_LOW                0x0
-+#define CS_HIGH               ID_CS /* HOST_CNTL_ID_PROM_SEL */
-+#define CLK_LOW               0x0
-+#define CLK_HIGH      ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */
-+#define SI_HIGH               ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */
-+#define EEPROM_DELAY  400 /* microseconds */
-+
-+/* Read from EEPROM = 0000 0011b */
-+unsigned int readtab[] = {
-+      CS_HIGH | CLK_HIGH,
-+      CS_LOW | CLK_LOW,
-+      CLK_HIGH,               /* 0 */
-+      CLK_LOW,
-+      CLK_HIGH,               /* 0 */
-+      CLK_LOW,
-+      CLK_HIGH,               /* 0 */
-+      CLK_LOW,
-+      CLK_HIGH,               /* 0 */
-+      CLK_LOW,
-+      CLK_HIGH,               /* 0 */
-+      CLK_LOW,
-+      CLK_HIGH,               /* 0 */
-+      CLK_LOW | SI_HIGH,
-+      CLK_HIGH | SI_HIGH,     /* 1 */
-+      CLK_LOW | SI_HIGH,
-+      CLK_HIGH | SI_HIGH      /* 1 */
-+};     
-+ 
-+/* Clock to read from/write to the EEPROM */
-+unsigned int clocktab[] = {
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW,
-+      CLK_HIGH,
-+      CLK_LOW
-+};     
-+
-+
-+#endif /* _HE_H_ */
-diff -urN linux-2.4.20/drivers/atm/horizon.c linux-2.4.20-atm/drivers/atm/horizon.c
---- linux-2.4.20/drivers/atm/horizon.c Sat Aug  3 02:39:43 2002
-+++ linux-2.4.20-atm/drivers/atm/horizon.c     Wed May 28 01:58:41 2003
-@@ -1765,13 +1765,13 @@
-   
-   {
-     unsigned int tx_len = skb->len;
--    unsigned int tx_iovcnt = ATM_SKB(skb)->iovcnt;
-+    unsigned int tx_nr_frags = skb_shinfo(skb)->nr_frags;
-     // remember this so we can free it later
-     dev->tx_skb = skb;
-     
--    if (tx_iovcnt) {
-+    if (tx_nr_frags) {
-       // scatter gather transfer
--      dev->tx_regions = tx_iovcnt;
-+      dev->tx_regions = tx_nr_frags;
-       dev->tx_iovec = (struct iovec *) skb->data;
-       dev->tx_bytes = 0;
-       PRINTD (DBG_TX|DBG_BUS, "TX start scatter-gather transfer (iovec %p, len %d)",
-@@ -2189,14 +2189,6 @@
-   }
- #endif
-   
--  // deal with possibly wildcarded VCs
--  error = atm_find_ci (atm_vcc, &vpi, &vci);
--  if (error) {
--    PRINTD (DBG_WARN|DBG_VCC, "atm_find_ci failed!");
--    return error;
--  }
--  PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
--  
-   error = vpivci_to_channel (&channel, vpi, vci);
-   if (error) {
-     PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci);
-diff -urN linux-2.4.20/drivers/atm/idt77252.c linux-2.4.20-atm/drivers/atm/idt77252.c
---- linux-2.4.20/drivers/atm/idt77252.c        Wed May 28 01:53:45 2003
-+++ linux-2.4.20-atm/drivers/atm/idt77252.c    Wed May 28 01:58:41 2003
-@@ -1054,15 +1054,17 @@
-               return;
-       }
-+      read_lock(&vcc_sklist_lock);
-       vc = card->vcs[VPCI2VC(card, vpi, vci)];
--      if (!vc || !test_bit(VCF_RX, &vc->flags)) {
-+      if (!vc || !test_bit(VCF_RX, &vc->flags) || !(vcc = vc->rx_vcc)) {
-+              read_unlock(&vcc_sklist_lock);
-               printk("%s: SDU received on non RX vc %u.%u\n",
-                      card->name, vpi, vci);
-               recycle_rx_skb(card, skb);
-               return;
-       }
--
--      vcc = vc->rx_vcc;
-+      vcc_hold(vcc);
-+      read_unlock(&vcc_sklist_lock);
-       pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(skb),
-                           skb->end - skb->data, PCI_DMA_FROMDEVICE);
-@@ -1106,6 +1108,7 @@
-                       cell += ATM_CELL_PAYLOAD;
-               }
-+              vcc_put(vcc);
-               recycle_rx_skb(card, skb);
-               return;
-       }
-@@ -1113,6 +1116,7 @@
-               printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n",
-                      card->name, vcc->qos.aal);
-               recycle_rx_skb(card, skb);
-+              vcc_put(vcc);
-               return;
-       }
-       skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD;
-@@ -1142,12 +1146,14 @@
-                                card->name, len, rpp->len, readl(SAR_REG_CDC));
-                       recycle_rx_pool_skb(card, rpp);
-                       atomic_inc(&vcc->stats->rx_err);
-+                      vcc_put(vcc);
-                       return;
-               }
-               if (stat & SAR_RSQE_CRC) {
-                       RXPRINTK("%s: AAL5 CRC error.\n", card->name);
-                       recycle_rx_pool_skb(card, rpp);
-                       atomic_inc(&vcc->stats->rx_err);
-+                      vcc_put(vcc);
-                       return;
-               }
-               if (rpp->count > 1) {
-@@ -1159,9 +1165,11 @@
-                                        card->name);
-                               recycle_rx_pool_skb(card, rpp);
-                               atomic_inc(&vcc->stats->rx_err);
-+                              vcc_put(vcc);
-                               return;
-                       }
-                       if (!atm_charge(vcc, skb->truesize)) {
-+                              vcc_put(vcc);
-                               recycle_rx_pool_skb(card, rpp);
-                               dev_kfree_skb(skb);
-                               return;
-@@ -1181,6 +1189,7 @@
-                       vcc->push(vcc, skb);
-                       atomic_inc(&vcc->stats->rx);
-+                      vcc_put(vcc);
-                       return;
-               }
-@@ -1189,6 +1198,7 @@
-               flush_rx_pool(card, rpp);
-               if (!atm_charge(vcc, skb->truesize)) {
-+                      vcc_put(vcc);
-                       recycle_rx_skb(card, skb);
-                       return;
-               }
-@@ -1212,8 +1222,10 @@
-                       add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
-               else
-                       add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
-+              vcc_put(vcc);
-               return;
-       }
-+      vcc_put(vcc);
- }
- static void
-@@ -1988,7 +2000,7 @@
-               return -EINVAL;
-       }
--      if (ATM_SKB(skb)->iovcnt != 0) {
-+      if (skb_shinfo(skb)->nr_frags != 0) {
-               printk("%s: No scatter-gather yet.\n", card->name);
-               atomic_inc(&vcc->stats->tx_err);
-               dev_kfree_skb(skb);
-@@ -2025,8 +2037,7 @@
-               atomic_inc(&vcc->stats->tx_err);
-               return -ENOMEM;
-       }
--      atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
--      ATM_SKB(skb)->iovcnt = 0;
-+      atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
-       memcpy(skb_put(skb, 52), cell, 52);
-@@ -2349,6 +2360,7 @@
-       if (test_bit(VCF_RX, &vc->flags))
-               return -EBUSY;
-+      vcc_hold(vcc);
-       vc->rx_vcc = vcc;
-       set_bit(VCF_RX, &vc->flags);
-@@ -2403,40 +2415,6 @@
- }
- static int
--idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci)
--{
--      struct atm_vcc *walk;
--
--      if (*vpi == ATM_VPI_ANY) {
--              *vpi = 0;
--              walk = vcc->dev->vccs;
--              while (walk) {
--                      if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
--                              (*vpi)++;
--                              walk = vcc->dev->vccs;
--                              continue;
--                      }
--                      walk = walk->next;
--              }
--      }
--
--      if (*vci == ATM_VCI_ANY) {
--              *vci = ATM_NOT_RSV_VCI;
--              walk = vcc->dev->vccs;
--              while (walk) {
--                      if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
--                              (*vci)++;
--                              walk = vcc->dev->vccs;
--                              continue;
--                      }
--                      walk = walk->next;
--              }
--      }
--
--      return 0;
--}
--
--static int
- idt77252_open(struct atm_vcc *vcc, short vpi, int vci)
- {
-       struct atm_dev *dev = vcc->dev;
-@@ -2446,8 +2424,6 @@
-       unsigned int inuse;
-       int error;
--      idt77252_find_vcc(vcc, &vpi, &vci);
--
-       if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
-               return 0;
-@@ -2565,6 +2541,8 @@
-               spin_lock_irqsave(&vc->lock, flags);
-               clear_bit(VCF_RX, &vc->flags);
-               vc->rx_vcc = NULL;
-+              barrier();
-+              vcc_put(vcc);
-               spin_unlock_irqrestore(&vc->lock, flags);
-               if ((vcc->vci == 3) || (vcc->vci == 4))
-diff -urN linux-2.4.20/drivers/atm/iphase.c linux-2.4.20-atm/drivers/atm/iphase.c
---- linux-2.4.20/drivers/atm/iphase.c  Wed May 28 01:53:45 2003
-+++ linux-2.4.20-atm/drivers/atm/iphase.c      Wed May 28 01:58:41 2003
-@@ -1122,13 +1122,17 @@
-             IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
-             return -1;
-         }
-+        read_lock(&vcc_sklist_lock);
-       vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];  
-       if (!vcc)  
-       {      
-+                read_unlock(&vcc_sklist_lock);
-                 free_desc(dev, desc); 
-               printk("IA: null vcc, drop PDU\n");  
-               return -1;  
-       }  
-+        vcc_hold(vcc);
-+        read_unlock(&vcc_sklist_lock);
-         
-   
-       /* might want to check the status bits for errors */  
-@@ -1185,8 +1189,6 @@
-         }
-       skb_put(skb,len);  
-         // pwang_test
--        ATM_SKB(skb)->vcc = vcc;
--        ATM_SKB(skb)->iovcnt = 0;
-         ATM_DESC(skb) = desc;        
-       skb_queue_tail(&iadev->rx_dma_q, skb);  
-@@ -1205,7 +1207,8 @@
-       udelay(1);  
-       /* Increment transaction counter */  
-       writel(1, iadev->dma+IPHASE5575_RX_COUNTER);   
--out:  return 0;  
-+out:    vcc_put(vcc);
-+      return 0;  
- out_free_desc:
-         free_desc(dev, desc);
-         goto out;
-@@ -1283,6 +1286,7 @@
-   struct dle *dle, *cur_dle;  
-   u_int dle_lp;  
-   int len;
-+  struct rx_buf_desc *buf_desc_ptr;  
-   iadev = INPH_IA_DEV(dev);  
-  
-   /* free all the dles done, that is just update our own dle read pointer   
-@@ -1293,6 +1297,7 @@
-   dle = iadev->rx_dle_q.read;  
-   dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);  
-   cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));  
-+  read_lock(&vcc_sklist_lock);
-   while(dle != cur_dle)  
-   {  
-       /* free the DMAed skb */  
-@@ -1300,6 +1305,9 @@
-       if (!skb)  
-          goto INCR_DLE;
-       desc = ATM_DESC(skb);
-+      buf_desc_ptr = (struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR;
-+      buf_desc_ptr += desc;
-+      vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];
-       free_desc(dev, desc);  
-                
-       if (!(len = skb->len))
-@@ -1316,7 +1324,6 @@
-         pci_unmap_single(iadev->pci, iadev->rx_dle_q.write->sys_pkt_addr,
-               len, PCI_DMA_FROMDEVICE);
-           /* no VCC related housekeeping done as yet. lets see */  
--          vcc = ATM_SKB(skb)->vcc;
-         if (!vcc) {
-             printk("IA: null vcc\n");  
-               dev_kfree_skb_any(skb);
-@@ -1360,6 +1367,7 @@
-           printk("\n");)
-         IF_RX(printk("rx_dle_intr: skb push");)  
-+        ATM_SKB(skb)->vcc = vcc;
-         vcc->push(vcc,skb);  
-         atomic_inc(&vcc->stats->rx);
-           iadev->rx_pkt_cnt++;
-@@ -1368,6 +1376,7 @@
-       if (++dle == iadev->rx_dle_q.end)  
-         dle = iadev->rx_dle_q.start;  
-   }  
-+  read_unlock(&vcc_sklist_lock);
-   iadev->rx_dle_q.read = dle;  
-   
-   /* if the interrupts are masked because there were no free desc available,  
-@@ -1425,6 +1434,7 @@
-       if (iadev->rx_open[vcc->vci])  
-               printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n",  
-                       vcc->dev->number, vcc->vci);  
-+      vcc_hold(vcc);
-       iadev->rx_open[vcc->vci] = vcc;  
-       return 0;  
- }  
-@@ -1725,15 +1735,14 @@
-                   printk("tx_dle_intr: vcc is null\n");
-                 spin_unlock_irqrestore(&iadev->tx_lock, flags);
-                   dev_kfree_skb_any(skb);
--
--                  return;
-+                  goto cont_loop;
-             }
-             iavcc = INPH_IA_VCC(vcc);
-             if (!iavcc) {
-                   printk("tx_dle_intr: iavcc is null\n");
-                 spin_unlock_irqrestore(&iadev->tx_lock, flags);
-                   dev_kfree_skb_any(skb);
--                  return;
-+                  goto cont_loop;
-             }
-             if (vcc->qos.txtp.pcr >= iadev->rate_limit) {
-                if ((vcc->pop) && (skb->len != 0))
-@@ -1749,6 +1758,7 @@
-                skb_queue_tail(&iavcc->txing_skb, skb);
-             }
-             IF_EVENT(printk("tx_dle_intr: enque skb = 0x%x \n", (u32)skb);)
-+cont_loop:
-             if (++dle == iadev->tx_dle_q.end)
-                  dle = iadev->tx_dle_q.start;
-         }
-@@ -2705,6 +2715,8 @@
-            // Drain the packets
-            rx_dle_intr(vcc->dev); 
-            iadev->rx_open[vcc->vci] = 0;
-+           barrier();
-+           vcc_put(vcc);
-         }
-       kfree(INPH_IA_VCC(vcc));  
-         ia_vcc = NULL;
-@@ -2724,12 +2736,6 @@
-               INPH_IA_VCC(vcc) = NULL;  
-       }  
-       iadev = INPH_IA_DEV(vcc->dev);  
--      error = atm_find_ci(vcc, &vpi, &vci);  
--      if (error)   
--      {  
--          printk("iadev: atm_find_ci returned error %d\n", error);  
--          return error;  
--      }  
-       vcc->vpi = vpi;  
-       vcc->vci = vci;  
-       if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)  
-diff -urN linux-2.4.20/drivers/atm/lanai.c linux-2.4.20-atm/drivers/atm/lanai.c
---- linux-2.4.20/drivers/atm/lanai.c   Fri Nov 29 00:53:12 2002
-+++ linux-2.4.20-atm/drivers/atm/lanai.c       Wed May 28 01:58:41 2003
-@@ -1820,10 +1820,10 @@
- {
-       vci_t vci = SERVICE_GET_VCI(s);
-       struct lanai_vcc *lvcc;
--      vcclist_read_lock();
-+      read_lock(&vcc_sklist_lock);
-       lvcc = lanai->vccs[vci];
-       if (lvcc == NULL) {
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               DPRINTK("(itf %d) got service entry 0x%X for nonexistent "
-                   "vcc %d\n", lanai->number, s, vci);
-               if (s & SERVICE_TX)
-@@ -1834,7 +1834,7 @@
-       }
-       if (s & SERVICE_TX) {                   /* segmentation interrupt */
-               if (lvcc->tx.atmvcc == NULL) {
--                      vcclist_read_unlock();
-+                      read_unlock(&vcc_sklist_lock);
-                       DPRINTK("(itf %d) got service entry 0x%X for non-TX "
-                           "vcc %d\n", lanai->number, s, vci);
-                       lanai->stats.service_notx++;
-@@ -1842,18 +1842,18 @@
-               }
-               vci_bitfield_set(&lanai->transmit_ready, vci);
-               lvcc->tx.endptr = SERVICE_GET_END(s);
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               return 1;
-       }
-       if (lvcc->rx.atmvcc == NULL) {
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               DPRINTK("(itf %d) got service entry 0x%X for non-RX "
-                   "vcc %d\n", lanai->number, s, vci);
-               lanai->stats.service_norx++;
-               return 0;
-       }
-       if (lvcc->rx.atmvcc->qos.aal != ATM_AAL5) {
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
-                   "vcc %d\n", lanai->number, s, vci);
-               lanai->stats.service_rxnotaal5++;
-@@ -1862,12 +1862,12 @@
-       }
-       if ((s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)) == 0) {
-               vcc_rx_aal5(lvcc, SERVICE_GET_END(s));
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               return 0;
-       }
-       if (s & SERVICE_TRASH) {
-               int bytes;
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               DPRINTK("got trashed rx pdu on vci %d\n", vci);
-               atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
-               lvcc->stats.x.aal5.service_trash++;
-@@ -1880,7 +1880,7 @@
-               return 0;
-       }
-       if (s & SERVICE_STREAM) {
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
-               lvcc->stats.x.aal5.service_stream++;
-               printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
-@@ -1893,7 +1893,7 @@
-       lvcc->stats.x.aal5.service_rxcrc++;
-       lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
-       cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
--      vcclist_read_unlock();
-+      read_unlock(&vcc_sklist_lock);
-       return 0;
- }
-@@ -1924,11 +1924,11 @@
-       reg_write(lanai, wreg, ServRead_Reg);
-       if (ntx != 0) {
-               spin_lock(&lanai->txlock);
--              vcclist_read_lock();
-+              read_lock(&vcc_sklist_lock);
-               vci_bitfield_iterate(lanai, &lanai->transmit_ready,
-                   iter_transmit);
-               vci_bitfield_init(&lanai->transmit_ready);
--              vcclist_read_unlock();
-+              read_unlock(&vcc_sklist_lock);
-               spin_unlock(&lanai->txlock);
-       }
- }
-@@ -2785,7 +2785,7 @@
-               return sprintf(page, "resets: dma=%d, card=%d\n",
-                   lanai->stats.dma_reenable, lanai->stats.card_reset);
-       /* At this point, "left" should be the VCI we're looking for */
--      vcclist_read_lock();
-+      read_lock(&vcc_sklist_lock);
-       for (; ; left++) {
-               if (left >= NUM_VCI) {
-                       left = 0;
-@@ -2821,7 +2821,7 @@
-       page[left++] = '\n';
-       page[left] = '\0';
-     out:
--      vcclist_read_unlock();
-+      read_unlock(&vcc_sklist_lock);
-       return left;
- }
- #endif /* CONFIG_PROC_FS */
-@@ -2842,7 +2842,6 @@
-       phy_get:        NULL,
-       feedback:       NULL,
-       change_qos:     lanai_change_qos,
--      free_rx_skb:    NULL,
-       proc_read:      lanai_proc_read
- };
-diff -urN linux-2.4.20/drivers/atm/nicstar.c linux-2.4.20-atm/drivers/atm/nicstar.c
---- linux-2.4.20/drivers/atm/nicstar.c Wed May 28 01:53:45 2003
-+++ linux-2.4.20-atm/drivers/atm/nicstar.c     Wed May 28 01:58:41 2003
-@@ -941,9 +941,15 @@
-       return error;
-    }
-       
--   if (ns_parse_mac(mac[i], card->atmdev->esi))
-+   if (ns_parse_mac(mac[i], card->atmdev->esi)) {
-       nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
-                          card->atmdev->esi, 6);
-+      if (!memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6)) {
-+         nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,
-+                         card->atmdev->esi, 6);
-+      }
-+   }
-+
-    printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i,
-           card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2],
-@@ -1433,7 +1439,6 @@
- {
-    ns_dev *card;
-    vc_map *vc;
--   int error;
-    unsigned long tmpl, modl;
-    int tcr, tcra;     /* target cell rate, and absolute value */
-    int n = 0;         /* Number of entries in the TST. Initialized to remove
-@@ -1453,11 +1458,6 @@
-       return -EINVAL;
-    }
--   if ((error = atm_find_ci(vcc, &vpi, &vci)))
--   {
--      PRINTK("nicstar%d: error in atm_find_ci().\n", card->index);
--      return error;
--   }
-    vc = &(card->vcmap[vpi << card->vcibits | vci]);
-    vcc->vpi = vpi;
-    vcc->vci = vci;
-@@ -1597,6 +1597,7 @@
-          u32 status;
-       
-          vc->rx = 1;
-+         vcc_hold(vcc);
-          vc->rx_vcc = vcc;
-          vc->rx_iov = NULL;
-@@ -1646,6 +1647,9 @@
-       spin_unlock_irqrestore(&card->res_lock, flags);
-       
-       vc->rx = 0;
-+      vc->rx_vcc = NULL;
-+      barrier();
-+      vcc_put(vcc);
-       if (vc->rx_iov != NULL)
-       {
-        struct sk_buff *iovb;
-@@ -1659,9 +1663,9 @@
-               card->index);
-          iovb = vc->rx_iov;
-          recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
--                             ATM_SKB(iovb)->iovcnt);
--         ATM_SKB(iovb)->iovcnt = 0;
--         ATM_SKB(iovb)->vcc = NULL;
-+                             NS_SKB(iovb)->iovcnt);
-+         NS_SKB(iovb)->iovcnt = 0;
-+         NS_SKB(iovb)->vcc = NULL;
-          ns_grab_int_lock(card, flags);
-          recycle_iov_buf(card, iovb);
-          spin_unlock_irqrestore(&card->int_lock, flags);
-@@ -1859,7 +1863,7 @@
-       return -EINVAL;
-    }
-    
--   if (ATM_SKB(skb)->iovcnt != 0)
-+   if (skb_shinfo(skb)->nr_frags != 0)
-    {
-       printk("nicstar%d: No scatter-gather yet.\n", card->index);
-       atomic_inc(&vcc->stats->tx_err);
-@@ -2203,16 +2207,18 @@
-       return;
-    }
-    
-+   read_lock(&vcc_sklist_lock);
-    vc = &(card->vcmap[vpi << card->vcibits | vci]);
--   if (!vc->rx)
-+   if (!vc->rx || !(vcc = vc->rx_vcc))
-    {
-+      read_unlock(&vcc_sklist_lock);
-       RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n",
-              card->index, vpi, vci);
-       recycle_rx_buf(card, skb);
-       return;
-    }
--
--   vcc = vc->rx_vcc;
-+   vcc_hold(vcc);
-+   read_unlock(&vcc_sklist_lock);
-    if (vcc->qos.aal == ATM_AAL0)
-    {
-@@ -2252,7 +2258,7 @@
-          atomic_inc(&vcc->stats->rx);
-          cell += ATM_CELL_PAYLOAD;
-       }
--
-+      vcc_put(vcc);
-       recycle_rx_buf(card, skb);
-       return;
-    }
-@@ -2269,6 +2275,7 @@
-        {
-           printk("nicstar%d: Out of iovec buffers.\n", card->index);
-             atomic_inc(&vcc->stats->rx_drop);
-+            vcc_put(vcc);
-             recycle_rx_buf(card, skb);
-             return;
-        }
-@@ -2284,30 +2291,30 @@
-           }
-        }
-       vc->rx_iov = iovb;
--      ATM_SKB(iovb)->iovcnt = 0;
-+      NS_SKB(iovb)->iovcnt = 0;
-       iovb->len = 0;
-       iovb->tail = iovb->data = iovb->head;
--      ATM_SKB(iovb)->vcc = vcc;
-+      NS_SKB(iovb)->vcc = vcc;
-       /* IMPORTANT: a pointer to the sk_buff containing the small or large
-                     buffer is stored as iovec base, NOT a pointer to the 
-                   small or large buffer itself. */
-    }
--   else if (ATM_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
-+   else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
-    {
-       printk("nicstar%d: received too big AAL5 SDU.\n", card->index);
-       atomic_inc(&vcc->stats->rx_err);
-       recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS);
--      ATM_SKB(iovb)->iovcnt = 0;
-+      NS_SKB(iovb)->iovcnt = 0;
-       iovb->len = 0;
-       iovb->tail = iovb->data = iovb->head;
--      ATM_SKB(iovb)->vcc = vcc;
-+      NS_SKB(iovb)->vcc = vcc;
-    }
--   iov = &((struct iovec *) iovb->data)[ATM_SKB(iovb)->iovcnt++];
-+   iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++];
-    iov->iov_base = (void *) skb;
-    iov->iov_len = ns_rsqe_cellcount(rsqe) * 48;
-    iovb->len += iov->iov_len;
--   if (ATM_SKB(iovb)->iovcnt == 1)
-+   if (NS_SKB(iovb)->iovcnt == 1)
-    {
-       if (skb->list != &card->sbpool.queue)
-       {
-@@ -2317,11 +2324,12 @@
-          atomic_inc(&vcc->stats->rx_err);
-          recycle_rx_buf(card, skb);
-          vc->rx_iov = NULL;
-+         vcc_put(vcc);
-          recycle_iov_buf(card, iovb);
-          return;
-       }
-    }
--   else /* ATM_SKB(iovb)->iovcnt >= 2 */
-+   else /* NS_SKB(iovb)->iovcnt >= 2 */
-    {
-       if (skb->list != &card->lbpool.queue)
-       {
-@@ -2330,8 +2338,9 @@
-          which_list(card, skb);
-          atomic_inc(&vcc->stats->rx_err);
-          recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
--                             ATM_SKB(iovb)->iovcnt);
-+                             NS_SKB(iovb)->iovcnt);
-          vc->rx_iov = NULL;
-+         vcc_put(vcc);
-          recycle_iov_buf(card, iovb);
-        return;
-       }
-@@ -2354,15 +2363,16 @@
-             printk(".\n");
-          atomic_inc(&vcc->stats->rx_err);
-          recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
--         ATM_SKB(iovb)->iovcnt);
-+         NS_SKB(iovb)->iovcnt);
-        vc->rx_iov = NULL;
-+         vcc_put(vcc);
-          recycle_iov_buf(card, iovb);
-        return;
-       }
-       /* By this point we (hopefully) have a complete SDU without errors. */
--      if (ATM_SKB(iovb)->iovcnt == 1) /* Just a small buffer */
-+      if (NS_SKB(iovb)->iovcnt == 1)  /* Just a small buffer */
-       {
-          /* skb points to a small buffer */
-          if (!atm_charge(vcc, skb->truesize))
-@@ -2384,7 +2394,7 @@
-             atomic_inc(&vcc->stats->rx);
-          }
-       }
--      else if (ATM_SKB(iovb)->iovcnt == 2)    /* One small plus one large buffer */
-+      else if (NS_SKB(iovb)->iovcnt == 2)     /* One small plus one large buffer */
-       {
-          struct sk_buff *sb;
-@@ -2461,8 +2471,9 @@
-                printk("nicstar%d: Out of huge buffers.\n", card->index);
-                atomic_inc(&vcc->stats->rx_drop);
-                recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
--                                   ATM_SKB(iovb)->iovcnt);
-+                                   NS_SKB(iovb)->iovcnt);
-                vc->rx_iov = NULL;
-+               vcc_put(vcc);
-                recycle_iov_buf(card, iovb);
-                return;
-             }
-@@ -2499,7 +2510,7 @@
-          if (!atm_charge(vcc, hb->truesize))
-        {
--            recycle_iovec_rx_bufs(card, iov, ATM_SKB(iovb)->iovcnt);
-+            recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt);
-             if (card->hbpool.count < card->hbnr.max)
-             {
-                skb_queue_tail(&card->hbpool.queue, hb);
-@@ -2522,7 +2533,7 @@
-                         0, 0);
-             /* Copy all large buffers to the huge buffer and free them */
--            for (j = 1; j < ATM_SKB(iovb)->iovcnt; j++)
-+            for (j = 1; j < NS_SKB(iovb)->iovcnt; j++)
-             {
-                lb = (struct sk_buff *) iov->iov_base;
-                tocopy = MIN(remaining, iov->iov_len);
-@@ -2550,7 +2561,7 @@
-       vc->rx_iov = NULL;
-       recycle_iov_buf(card, iovb);
-    }
--
-+   vcc_put(vcc);
- }
-diff -urN linux-2.4.20/drivers/atm/nicstar.h linux-2.4.20-atm/drivers/atm/nicstar.h
---- linux-2.4.20/drivers/atm/nicstar.h Thu Oct 25 22:53:46 2001
-+++ linux-2.4.20-atm/drivers/atm/nicstar.h     Wed May 28 01:58:41 2003
-@@ -96,6 +96,7 @@
- /* ESI stuff ******************************************************************/
- #define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C
-+#define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6
- /* #defines *******************************************************************/
-@@ -748,6 +749,14 @@
-    int tbd_count;
- } vc_map;
-+
-+struct ns_skb_data
-+{
-+      struct atm_vcc *vcc;
-+      int iovcnt;
-+};
-+
-+#define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb))
- typedef struct ns_dev
- {
-diff -urN linux-2.4.20/drivers/atm/zatm.c linux-2.4.20-atm/drivers/atm/zatm.c
---- linux-2.4.20/drivers/atm/zatm.c    Fri Sep 14 23:40:00 2001
-+++ linux-2.4.20-atm/drivers/atm/zatm.c        Wed May 28 01:58:41 2003
-@@ -827,10 +827,10 @@
-       vcc = ATM_SKB(skb)->vcc;
-       zatm_dev = ZATM_DEV(vcc->dev);
-       zatm_vcc = ZATM_VCC(vcc);
--      EVENT("iovcnt=%d\n",ATM_SKB(skb)->iovcnt,0);
-+      EVENT("nr_frags=%d\n",skb_shinfo(skb)->nr_frags,0);
-       save_flags(flags);
-       cli();
--      if (!ATM_SKB(skb)->iovcnt) {
-+      if (!skb_shinfo(skb)->nr_frags) {
-               if (zatm_vcc->txing == RING_ENTRIES-1) {
-                       restore_flags(flags);
-                       return RING_BUSY;
-@@ -1579,8 +1579,6 @@
-       DPRINTK(">zatm_open\n");
-       zatm_dev = ZATM_DEV(vcc->dev);
-       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)
-diff -urN linux-2.4.20/include/linux/atm_he.h linux-2.4.20-atm/include/linux/atm_he.h
---- linux-2.4.20/include/linux/atm_he.h        Thu Jan  1 01:00:00 1970
-+++ linux-2.4.20-atm/include/linux/atm_he.h    Wed May 28 01:58:41 2003
-@@ -0,0 +1,20 @@
-+/* atm_he.h */
-+
-+#ifndef LINUX_ATM_HE_H
-+#define LINUX_ATM_HE_H
-+
-+#include <linux/atmioc.h>
-+
-+#define HE_GET_REG    _IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
-+
-+#define HE_REGTYPE_PCI        1
-+#define HE_REGTYPE_RCM        2
-+#define HE_REGTYPE_TCM        3
-+#define HE_REGTYPE_MBOX       4
-+
-+struct he_ioctl_reg {
-+      unsigned addr, val;
-+      char type;
-+};
-+
-+#endif /* LINUX_ATM_HE_H */
-diff -urN linux-2.4.20/include/linux/atm_tcp.h linux-2.4.20-atm/include/linux/atm_tcp.h
---- linux-2.4.20/include/linux/atm_tcp.h       Fri Dec 29 23:35:47 2000
-+++ linux-2.4.20-atm/include/linux/atm_tcp.h   Wed May 28 01:58:41 2003
-@@ -68,7 +68,7 @@
-       struct module *owner;
- };
--extern struct atm_tcp_ops atm_tcp_ops;
-+extern struct atm_tcp_ops *atm_tcp_ops;
- #endif
-diff -urN linux-2.4.20/include/linux/atmdev.h linux-2.4.20-atm/include/linux/atmdev.h
---- linux-2.4.20/include/linux/atmdev.h        Wed May 28 01:54:12 2003
-+++ linux-2.4.20-atm/include/linux/atmdev.h    Wed May 28 01:58:41 2003
-@@ -30,10 +30,9 @@
- #define ATM_DS3_PCR   (8000*12)
-                       /* DS3: 12 cells in a 125 usec time slot */
--#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 atm_sk(__sk)  ((struct atm_vcc *)(__sk)->protinfo.af_atm)
-+#define ATM_SD(s)     (atm_sk((s)->sk))
- #define __AAL_STAT_ITEMS \
-@@ -292,10 +291,6 @@
-       struct atm_sap  sap;            /* SAP */
-       void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
-       void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
--      struct sk_buff *(*alloc_tx)(struct atm_vcc *vcc,unsigned int size);
--                                      /* TX allocation routine - can be */
--                                      /* 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 */
-@@ -303,15 +298,10 @@
-       struct k_atm_aal_stats *stats;  /* pointer to AAL stats group */
-       wait_queue_head_t sleep;        /* if socket is busy */
-       struct sock     *sk;            /* socket backpointer */
--      struct atm_vcc  *prev,*next;
-       /* SVC part --- may move later ------------------------------------- */
--      short           itf;            /* interface number */
-       struct sockaddr_atmsvc local;
-       struct sockaddr_atmsvc remote;
-       void (*callback)(struct atm_vcc *vcc);
--      struct sk_buff_head listenq;
--      int             backlog_quota;  /* number of connection requests we */
--                                      /* can still accept */
-       int             reply;          /* also used by ATMTCP */
-       /* Multipoint part ------------------------------------------------- */
-       struct atm_vcc  *session;       /* session VCC descriptor */
-@@ -337,8 +327,6 @@
-                                       /* (NULL) */
-       const char      *type;          /* device type name */
-       int             number;         /* device index */
--      struct atm_vcc  *vccs;          /* VCC table (or NULL) */
--      struct atm_vcc  *last;          /* last VCC (or undefined) */
-       void            *dev_data;      /* per-device data */
-       void            *phy_data;      /* private PHY date */
-       atm_dev_flags_t flags;          /* device flags (ATM_DF_*) */
-@@ -348,6 +336,8 @@
-       struct k_atm_dev_stats stats;   /* statistics */
-       char            signal;         /* signal status (ATM_PHY_SIG_*) */
-       int             link_rate;      /* link rate (default: OC3) */
-+      atomic_t        refcnt;         /* reference count */
-+      spinlock_t      lock;           /* protect internal members */
- #ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *proc_entry; /* proc entry */
-       char *proc_name;                /* proc entry name */
-@@ -388,8 +378,6 @@
-       void (*feedback)(struct atm_vcc *vcc,struct sk_buff *skb,
-           unsigned long start,unsigned long dest,int len);
-       int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags);
--      void (*free_rx_skb)(struct atm_vcc *vcc, struct sk_buff *skb);
--              /* @@@ temporary hack */
-       int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
-       struct module *owner;
- };
-@@ -404,53 +392,94 @@
- struct atm_skb_data {
-       struct atm_vcc  *vcc;           /* ATM VCC */
--      int             iovcnt;         /* 0 for "normal" operation */
-       unsigned long   atm_options;    /* ATM layer options */
- };
-+extern struct sock *vcc_sklist;
-+extern rwlock_t vcc_sklist_lock;
-+
- #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,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);
-+struct atm_dev *atm_dev_lookup(int number);
-+void atm_dev_hold(struct atm_dev *dev);
-+void atm_dev_release(struct atm_dev *dev);
- void shutdown_atm_dev(struct atm_dev *dev);
--void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev);
-+void vcc_insert_socket(struct atm_dev *dev, struct sock *sk);
-+void vcc_remove_socket(struct atm_dev *dev, struct sock *sk);
--/*
-- * This is approximately the algorithm used by alloc_skb.
-- *
-- */
-+static inline int atm_guess_pdu2truesize(int pdu_size)
-+{
-+      /* must match allocation in alloc_skb */
-+      return SKB_DATA_ALIGN(pdu_size) + sizeof(struct sk_buff);
-+}
-+
--static __inline__ int atm_guess_pdu2truesize(int pdu_size)
-+static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
- {
--      return ((pdu_size+15) & ~15) + sizeof(struct sk_buff);
-+      atomic_add(truesize, &vcc->sk->rmem_alloc);
- }
--static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize)
-+static inline void atm_return(struct atm_vcc *vcc,int truesize)
- {
--      atomic_add(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
-+      atomic_sub(truesize, &vcc->sk->rmem_alloc);
-+}
-+
-+
-+static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
-+{
-+      return (size+atomic_read(&vcc->sk->wmem_alloc)) < vcc->sk->sndbuf;
-+}
-+
-+
-+static inline struct atm_vcc *__vcc_lookup(struct atm_dev *dev, short vpi, int vci)
-+{
-+      struct atm_vcc *vcc;
-+      struct sock *s;
-+
-+      for(s = vcc_sklist; s; s = s->next) {
-+              vcc = atm_sk(s);
-+              if (vcc->vci == vci && vcc->vpi == vpi && vcc->dev == dev) return vcc;
-+      }
-+
-+      return NULL;
-+}
-+
-+
-+static inline struct atm_vcc *vcc_lookup(struct atm_dev *dev, short vpi, int vci)
-+{
-+      struct atm_vcc *vcc;
-+
-+      read_lock(&vcc_sklist_lock);
-+      if ((vcc = __vcc_lookup(dev, vpi, vci))) {
-+              sock_hold(vcc->sk);
-+              read_unlock(&vcc_sklist_lock);
-+              return vcc;
-+      }
-+      read_unlock(&vcc_sklist_lock);
-+      return NULL;
- }
--static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
-+static inline void vcc_hold(struct atm_vcc *vcc)
- {
--      atomic_sub(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
-+      sock_hold(vcc->sk);
- }
--static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
-+static inline void vcc_put(struct atm_vcc *vcc)
- {
--      return size+atomic_read(&vcc->sk->wmem_alloc)+ATM_PDU_OVHD < vcc->sk->sndbuf;
-+      sock_put(vcc->sk);
- }
- int atm_charge(struct atm_vcc *vcc,int truesize);
- struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
-     int gfp_flags);
--int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci);
- int atm_pcr_goal(struct atm_trafprm *tp);
- void atm_async_release_vcc(struct atm_vcc *vcc,int reply);
-diff -urN linux-2.4.20/include/linux/net.h linux-2.4.20-atm/include/linux/net.h
---- linux-2.4.20/include/linux/net.h   Thu Nov 22 20:46:19 2001
-+++ linux-2.4.20-atm/include/linux/net.h       Wed May 28 01:58:41 2003
-@@ -139,6 +139,7 @@
- extern int    sock_recvmsg(struct socket *, struct msghdr *m, int len, int flags);
- extern int    sock_readv_writev(int type, struct inode * inode, struct file * file,
-                                 const struct iovec * iov, long count, long size);
-+extern struct socket *sockfd_lookup(int fd, int *err);
- extern int    net_ratelimit(void);
- extern unsigned long net_random(void);
-diff -urN linux-2.4.20/include/net/atmclip.h linux-2.4.20-atm/include/net/atmclip.h
---- linux-2.4.20/include/net/atmclip.h Thu Nov 22 20:49:31 2001
-+++ linux-2.4.20-atm/include/net/atmclip.h     Wed May 28 01:58:41 2003
-@@ -55,13 +55,27 @@
- };
--extern struct atm_vcc *atmarpd; /* ugly */
- extern struct neigh_table clip_tbl;
-+extern struct atm_vcc *atmarpd; /* ugly */
- int clip_create(int number);
- int clip_mkip(struct atm_vcc *vcc,int timeout);
- int clip_setentry(struct atm_vcc *vcc,u32 ip);
- int clip_encap(struct atm_vcc *vcc,int mode);
--void atm_clip_init(void);
-+
-+struct atm_clip_ops {
-+      int (*clip_create)(int number);
-+      int (*clip_mkip)(struct atm_vcc *vcc,int timeout);
-+      int (*clip_setentry)(struct atm_vcc *vcc,u32 ip);
-+      int (*clip_encap)(struct atm_vcc *vcc,int mode);
-+      void (*clip_push)(struct atm_vcc *vcc,struct sk_buff *skb);
-+      int (*atm_init_atmarp)(struct atm_vcc *vcc);
-+      struct module *owner;
-+};
-+
-+#ifdef __KERNEL__
-+extern struct neigh_table *clip_tbl_hook;
-+extern struct atm_clip_ops *atm_clip_ops;
-+#endif
- #endif
-diff -urN linux-2.4.20/net/Config.in linux-2.4.20-atm/net/Config.in
---- linux-2.4.20/net/Config.in Sat Aug  3 02:39:46 2002
-+++ linux-2.4.20-atm/net/Config.in     Wed May 28 01:58:41 2003
-@@ -31,19 +31,19 @@
-    fi
- fi
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
--   bool 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM
--   if [ "$CONFIG_ATM" = "y" ]; then
-+   tristate 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM
-+   if [ "$CONFIG_ATM" != "n" ]; then
-       if [ "$CONFIG_INET" = "y" ]; then
--       bool '  Classical IP over ATM' CONFIG_ATM_CLIP
-+       dep_tristate '  Classical IP over ATM' CONFIG_ATM_CLIP $CONFIG_ATM
-        if [ "$CONFIG_ATM_CLIP" = "y" ]; then
-           bool '    Do NOT send ICMP if no neighbour' CONFIG_ATM_CLIP_NO_ICMP
-        fi
-       fi
--      tristate '  LAN Emulation (LANE) support' CONFIG_ATM_LANE
-+      dep_tristate '  LAN Emulation (LANE) support' CONFIG_ATM_LANE $CONFIG_ATM
-       if [ "$CONFIG_INET" = "y" -a "$CONFIG_ATM_LANE" != "n" ]; then
--       tristate '    Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA
-+       dep_tristate '    Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA $CONFIG_ATM
-       fi
--      tristate '  RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684
-+      dep_tristate '  RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684 $CONFIG_ATM
-       if [ "$CONFIG_ATM_BR2684" != "n" ]; then
-             bool '    Per-VC IP filter kludge' CONFIG_ATM_BR2684_IPFILTER
-       fi
-diff -urN linux-2.4.20/net/atm/Makefile linux-2.4.20-atm/net/atm/Makefile
---- linux-2.4.20/net/atm/Makefile      Sat Aug  3 02:39:46 2002
-+++ linux-2.4.20-atm/net/atm/Makefile  Wed May 28 01:58:41 2003
-@@ -14,32 +14,24 @@
- list-multi    := mpoa.o
- mpoa-objs     := mpc.o mpoa_caches.o mpoa_proc.o
--obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
-+obj-y := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
-+obj-m := $(O_TARGET)
--ifeq ($(CONFIG_ATM_CLIP),y)
--obj-y += clip.o
--NEED_IPCOM = ipcommon.o
--endif
--
--ifeq ($(CONFIG_ATM_BR2684),y)
--  NEED_IPCOM = ipcommon.o
--else
--  ifeq ($(CONFIG_ATM_BR2684),m)
--      NEED_IPCOM = ipcommon.o
--  endif
--endif
-+obj-$(CONFIG_ATM_CLIP) += clip.o
- obj-$(CONFIG_ATM_BR2684) += br2684.o
--ifeq ($(CONFIG_NET_SCH_ATM),y)
--NEED_IPCOM = ipcommon.o
-+ifneq ($(CONFIG_ATM_CLIP),n)
-+  ip-common-obj-y = ipcommon.o
- endif
--
--obj-y += $(NEED_IPCOM)
--
--ifeq ($(CONFIG_PROC_FS),y)
--obj-y += proc.o
-+ifneq ($(CONFIG_ATM_BR2684),n)
-+  ip-common-obj-y = ipcommon.o
-+endif
-+ifneq ($(CONFIG_NET_SCH_ATM),n)
-+  ip-common-obj-y = ipcommon.o
- endif
-+obj-y += $(ip-common-obj-y)
-+obj-$(CONFIG_PROC_FS) += proc.o
- obj-$(CONFIG_ATM_LANE) += lec.o
- obj-$(CONFIG_ATM_MPOA) += mpoa.o
- obj-$(CONFIG_PPPOATM) += pppoatm.o
-diff -urN linux-2.4.20/net/atm/addr.c linux-2.4.20-atm/net/atm/addr.c
---- linux-2.4.20/net/atm/addr.c        Fri Apr  6 19:51:19 2001
-+++ linux-2.4.20-atm/net/atm/addr.c    Wed May 28 01:58:41 2003
-@@ -36,14 +36,6 @@
- }
--/*
-- * Avoid modification of any list of local interfaces while reading it
-- * (which may involve page faults and therefore rescheduling)
-- */
--
--static DECLARE_MUTEX(local_lock);
--extern  spinlock_t atm_dev_lock;
--
- static void notify_sigd(struct atm_dev *dev)
- {
-       struct sockaddr_atmpvc pvc;
-@@ -60,13 +52,13 @@
- {
-       struct atm_dev_addr *this;
--      down(&local_lock);
-+      spin_lock(&dev->lock);
-       while (dev->local) {
-               this = dev->local;
-               dev->local = this->next;
-               kfree(this);
-       }
--      up(&local_lock);
-+      spin_unlock(&dev->lock);
-       notify_sigd(dev);
- }
-@@ -78,20 +70,20 @@
-       error = check_addr(addr);
-       if (error) return error;
--      down(&local_lock);
-+      spin_lock(&dev->lock);
-       for (walk = &dev->local; *walk; walk = &(*walk)->next)
-               if (identical(&(*walk)->addr,addr)) {
--                      up(&local_lock);
-+                      spin_unlock(&dev->lock);
-                       return -EEXIST;
-               }
--      *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_KERNEL);
-+      *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_ATOMIC);
-       if (!*walk) {
--              up(&local_lock);
-+              spin_unlock(&dev->lock);
-               return -ENOMEM;
-       }
-       (*walk)->addr = *addr;
-       (*walk)->next = NULL;
--      up(&local_lock);
-+      spin_unlock(&dev->lock);
-       notify_sigd(dev);
-       return 0;
- }
-@@ -104,17 +96,17 @@
-       error = check_addr(addr);
-       if (error) return error;
--      down(&local_lock);
-+      spin_lock(&dev->lock);
-       for (walk = &dev->local; *walk; walk = &(*walk)->next)
-               if (identical(&(*walk)->addr,addr)) break;
-       if (!*walk) {
--              up(&local_lock);
-+              spin_unlock(&dev->lock);
-               return -ENOENT;
-       }
-       this = *walk;
-       *walk = this->next;
-+      spin_unlock(&dev->lock);
-       kfree(this);
--      up(&local_lock);
-       notify_sigd(dev);
-       return 0;
- }
-@@ -125,21 +117,21 @@
-       struct atm_dev_addr *walk;
-       int total;
--      down(&local_lock);
-+      spin_lock(&dev->lock);
-       total = 0;
-       for (walk = dev->local; walk; walk = walk->next) {
-               total += sizeof(struct sockaddr_atmsvc);
-               if (total > size) {
--                      up(&local_lock);
-+                      spin_unlock(&dev->lock);
-                       return -E2BIG;
-               }
-               if (copy_to_user(u_buf,&walk->addr,
-                   sizeof(struct sockaddr_atmsvc))) {
--                      up(&local_lock);
-+                      spin_unlock(&dev->lock);
-                       return -EFAULT;
-               }
-               u_buf++;
-       }
--      up(&local_lock);
-+      spin_unlock(&dev->lock);
-       return total;
- }
-diff -urN linux-2.4.20/net/atm/atm_misc.c linux-2.4.20-atm/net/atm/atm_misc.c
---- linux-2.4.20/net/atm/atm_misc.c    Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/atm_misc.c        Wed May 28 01:58:41 2003
-@@ -43,63 +43,6 @@
- }
--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 (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 &&
--                  vcc->qos.rxtp.traffic_class != ATM_NONE)))
--                      return -EADDRINUSE;
--              /* allow VCCs with same VPI/VCI iff they don't collide on
--                 TX/RX (but we may refuse such sharing for other reasons,
--                 e.g. if protocol requires to have both channels) */
--      return 0;
--}
--
--
--int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
--{
--      static short p = 0; /* poor man's per-device cache */
--      static int c = 0;
--      short old_p;
--      int old_c;
--
--      if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY)
--              return check_ci(vcc,*vpi,*vci);
--      /* last scan may have left values out of bounds for current device */
--      if (*vpi != ATM_VPI_ANY) p = *vpi;
--      else if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
--      if (*vci != ATM_VCI_ANY) c = *vci;
--      else if (c < ATM_NOT_RSV_VCI || c >= 1 << vcc->dev->ci_range.vci_bits)
--                      c = ATM_NOT_RSV_VCI;
--      old_p = p;
--      old_c = c;
--      do {
--              if (!check_ci(vcc,p,c)) {
--                      *vpi = p;
--                      *vci = c;
--                      return 0;
--              }
--              if (*vci == ATM_VCI_ANY) {
--                      c++;
--                      if (c >= 1 << vcc->dev->ci_range.vci_bits)
--                              c = ATM_NOT_RSV_VCI;
--              }
--              if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
--                  *vpi == ATM_VPI_ANY) {
--                      p++;
--                      if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
--              }
--      }
--      while (old_p != p || old_c != c);
--      return -EADDRINUSE;
--}
--
--
- /*
-  * atm_pcr_goal returns the positive PCR if it should be rounded up, the
-  * negative PCR if it should be rounded down, and zero if the maximum available
-@@ -155,7 +98,6 @@
- EXPORT_SYMBOL(atm_charge);
- EXPORT_SYMBOL(atm_alloc_charge);
--EXPORT_SYMBOL(atm_find_ci);
- EXPORT_SYMBOL(atm_pcr_goal);
- EXPORT_SYMBOL(sonet_copy_stats);
- EXPORT_SYMBOL(sonet_subtract_stats);
-diff -urN linux-2.4.20/net/atm/br2684.c linux-2.4.20-atm/net/atm/br2684.c
---- linux-2.4.20/net/atm/br2684.c      Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/br2684.c  Wed May 28 01:58:41 2003
-@@ -189,7 +189,6 @@
-               return 0;
-               }
-       atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc);
--      ATM_SKB(skb)->iovcnt = 0;
-       ATM_SKB(skb)->atm_options = atmvcc->atm_options;
-       brdev->stats.tx_packets++;
-       brdev->stats.tx_bytes += skb->len;
-diff -urN linux-2.4.20/net/atm/clip.c linux-2.4.20-atm/net/atm/clip.c
---- linux-2.4.20/net/atm/clip.c        Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/clip.c    Wed May 28 01:58:41 2003
-@@ -7,6 +7,7 @@
- #include <linux/string.h>
- #include <linux/errno.h>
- #include <linux/kernel.h> /* for UINT_MAX */
-+#include <linux/module.h>
- #include <linux/netdevice.h>
- #include <linux/skbuff.h>
- #include <linux/wait.h>
-@@ -48,7 +49,6 @@
- static struct timer_list idle_timer;
- static int start_timer = 1;
--
- static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
- {
-       struct atmarp_ctrl *ctrl;
-@@ -127,6 +127,8 @@
-                       struct atmarp_entry *entry = NEIGH2ENTRY(n);
-                       struct clip_vcc *clip_vcc;
-+                      write_lock(&n->lock);
-+
-                       for (clip_vcc = entry->vccs; clip_vcc;
-                           clip_vcc = clip_vcc->next)
-                               if (clip_vcc->idle_timeout &&
-@@ -140,6 +142,7 @@
-                               }
-                       if (entry->vccs ||
-                           time_before(jiffies, entry->expires)) {
-+                              write_unlock(&n->lock);
-                               np = &n->next;
-                               continue;
-                       }
-@@ -151,12 +154,14 @@
-                               while ((skb = skb_dequeue(&n->arp_queue)) !=
-                                    NULL) 
-                                       dev_kfree_skb(skb);
-+                              write_unlock(&n->lock);
-                               np = &n->next;
-                               continue;
-                       }
-                       *np = n->next;
-                       DPRINTK("expired neigh %p\n",n);
-                       n->dead = 1;
-+                      write_unlock(&n->lock);
-                       neigh_release(n);
-               }
-       }
-@@ -218,6 +223,7 @@
-       clip_vcc->last_use = jiffies;
-       PRIV(skb->dev)->stats.rx_packets++;
-       PRIV(skb->dev)->stats.rx_bytes += skb->len;
-+      memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
-       netif_rx(skb);
- }
-@@ -427,7 +433,6 @@
-               ((u16 *) here)[3] = skb->protocol;
-       }
-       atomic_add(skb->truesize,&vcc->sk->wmem_alloc);
--      ATM_SKB(skb)->iovcnt = 0;
-       ATM_SKB(skb)->atm_options = vcc->atm_options;
-       entry->vccs->last_use = jiffies;
-       DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
-@@ -694,25 +699,21 @@
-               printk(KERN_ERR "atmarpd_close: closing with requests "
-                   "pending\n");
-       skb_queue_purge(&vcc->sk->receive_queue);
-+      MOD_DEC_USE_COUNT;
-       DPRINTK("(done)\n");
- }
- static struct atmdev_ops atmarpd_dev_ops = {
--      close:  atmarpd_close,
-+      .close = atmarpd_close,
- };
- static struct atm_dev atmarpd_dev = {
--      &atmarpd_dev_ops,
--      NULL,           /* no PHY */
--      "arpd",         /* type */
--      999,            /* dummy device number */
--      NULL,NULL,      /* pretend not to have any VCCs */
--      NULL,NULL,      /* no data */
--      { 0 },          /* no flags */
--      NULL,           /* no local address */
--      { 0 }           /* no ESI, no statistics */
-+      .ops =                  &atmarpd_dev_ops,
-+      .type =                 "arpd",
-+      .number =               999,
-+      .lock =                 SPIN_LOCK_UNLOCKED
- };
-@@ -732,7 +733,7 @@
-       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_insert_socket(&atmarpd_dev, vcc->sk);
-       vcc->push = NULL;
-       vcc->pop = NULL; /* crash */
-       vcc->push_oam = NULL; /* crash */
-@@ -746,10 +747,59 @@
-       return 0;
- }
-+static struct atm_clip_ops __atm_clip_ops = {
-+      .clip_create =          clip_create,
-+      .clip_mkip =            clip_mkip,
-+      .clip_setentry =        clip_setentry,
-+      .clip_encap =           clip_encap,
-+      .clip_push =            clip_push,
-+      .atm_init_atmarp =      atm_init_atmarp,
-+      .owner =                THIS_MODULE
-+};
--void atm_clip_init(void)
-+static int __init atm_clip_init(void)
- {
-+      /* we should use neigh_table_init() */
-       clip_tbl.lock = RW_LOCK_UNLOCKED;
-       clip_tbl.kmem_cachep = kmem_cache_create(clip_tbl.id,
-           clip_tbl.entry_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-+
-+
-+      /* so neigh_ifdown() doesn't complain */
-+      clip_tbl.proxy_timer.data = 0;
-+      clip_tbl.proxy_timer.function = 0;
-+      init_timer(&clip_tbl.proxy_timer);
-+      skb_queue_head_init(&clip_tbl.proxy_queue);
-+
-+
-+      atm_clip_ops = &__atm_clip_ops;
-+
-+      clip_tbl_hook = &clip_tbl;
-+
-+      return 0;
- }
-+
-+static void __exit atm_clip_exit(void)
-+{
-+      struct net_device *dev, *next;
-+
-+      atm_clip_ops = NULL;
-+      clip_tbl_hook = NULL;
-+
-+      neigh_ifdown(&clip_tbl, NULL);
-+      dev = clip_devs;
-+      while (dev) {
-+              next = PRIV(dev)->next;
-+              unregister_netdev(dev);
-+              kfree(dev);
-+              dev = next;
-+      }
-+      if (start_timer == 0) del_timer(&idle_timer);
-+
-+      kmem_cache_destroy(clip_tbl.kmem_cachep);
-+}
-+
-+module_init(atm_clip_init);
-+module_exit(atm_clip_exit);
-+
-+MODULE_LICENSE("GPL");
-diff -urN linux-2.4.20/net/atm/common.c linux-2.4.20-atm/net/atm/common.c
---- linux-2.4.20/net/atm/common.c      Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/common.c  Wed May 28 02:03:31 2003
-@@ -5,6 +5,7 @@
- #include <linux/config.h>
- #include <linux/module.h>
-+#include <linux/init.h>
- #include <linux/kmod.h>
- #include <linux/net.h>                /* struct socket, struct net_proto, struct
-                                  proto_ops */
-@@ -27,21 +27,22 @@
- #include <asm/atomic.h>
- #include <asm/poll.h>
- #include <asm/ioctls.h>
-+#include <asm/semaphore.h>
- #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- #include <linux/atmlec.h>
- #include "lec.h"
- #include "lec_arpc.h"
--struct atm_lane_ops atm_lane_ops;
--#endif
-+struct atm_lane_ops *atm_lane_ops;
- #ifdef CONFIG_ATM_LANE_MODULE
- EXPORT_SYMBOL(atm_lane_ops);
- #endif
-+#endif
- #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
- #include <linux/atmmpc.h>
- #include "mpc.h"
--struct atm_mpoa_ops atm_mpoa_ops;
-+struct atm_mpoa_ops *atm_mpoa_ops;
- #endif
- #ifdef CONFIG_ATM_MPOA_MODULE
- EXPORT_SYMBOL(atm_mpoa_ops);
-@@ -52,12 +53,20 @@
- #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
- #include <linux/atm_tcp.h>
-+struct atm_tcp_ops *atm_tcp_ops;
- #ifdef CONFIG_ATM_TCP_MODULE
--struct atm_tcp_ops atm_tcp_ops;
- EXPORT_SYMBOL(atm_tcp_ops);
- #endif
- #endif
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-+#include <net/atmclip.h>
-+struct atm_clip_ops *atm_clip_ops;
-+#ifdef CONFIG_ATM_CLIP_MODULE
-+EXPORT_SYMBOL(atm_clip_ops);
-+#endif
-+#endif
-+
- #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
- int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
- EXPORT_SYMBOL(pppoatm_ioctl_hook);
-@@ -74,9 +83,6 @@
- #include "common.h"           /* prototypes */
- #include "protocols.h"                /* atm_init_<transport> */
- #include "addr.h"             /* address registry */
--#ifdef CONFIG_ATM_CLIP
--#include <net/atmclip.h>      /* for clip_create */
--#endif
- #include "signaling.h"                /* for WAITING and sigd_attach */
-@@ -86,8 +92,6 @@
- #define DPRINTK(format,args...)
- #endif
--spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
--
- static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
- {
-       struct sk_buff *skb;
-@@ -99,78 +103,94 @@
-       }
-       while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
-       DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->sk->wmem_alloc),skb->truesize);
--      atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
-+      atomic_add(skb->truesize,&vcc->sk->wmem_alloc);
-       return skb;
- }
--int atm_create(struct socket *sock,int protocol,int family)
-+static void vcc_destruct(struct sock *sk)
-+{
-+      if (atomic_read(&sk->rmem_alloc))
-+              printk(KERN_WARNING "rmem leakage (%d bytes) detected.\n", atomic_read(&sk->rmem_alloc));
-+
-+      if (atomic_read(&sk->wmem_alloc))
-+              printk(KERN_WARNING "wmem leakage (%d bytes) detected.\n", atomic_read(&sk->wmem_alloc));
-+
-+      kfree(sk->protinfo.af_atm);
-+}
-+
-+
-+int vcc_create(struct socket *sock,int protocol,int family)
- {
-       struct sock *sk;
-       struct atm_vcc *vcc;
-       sock->sk = NULL;
-       if (sock->type == SOCK_STREAM) return -EINVAL;
--      if (!(sk = alloc_atm_vcc_sk(family))) return -ENOMEM;
--      vcc = sk->protinfo.af_atm;
-+      sk = sk_alloc(family, GFP_KERNEL, 1);
-+      if (!sk)
-+              return -ENOMEM;
-+      sock_init_data(NULL, sk);
-+
-+      vcc = atm_sk(sk) = kmalloc(sizeof(*vcc), GFP_KERNEL);
-+      if (!vcc) {
-+              sk_free(sk);
-+              return -ENOMEM;
-+      }
-+      memset(vcc, 0, sizeof(*vcc));
-+
-+      vcc->sk = sk;
-       memset(&vcc->flags,0,sizeof(vcc->flags));
-       vcc->dev = NULL;
--      vcc->alloc_tx = alloc_tx;
-       vcc->callback = NULL;
-       memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
-       memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
-       vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
--      atomic_set(&vcc->sk->wmem_alloc,0);
--      atomic_set(&vcc->sk->rmem_alloc,0);
-       vcc->push = NULL;
-       vcc->pop = NULL;
-       vcc->push_oam = NULL;
-       vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
-       vcc->atm_options = vcc->aal_options = 0;
-       init_waitqueue_head(&vcc->sleep);
--      skb_queue_head_init(&vcc->listenq);
-       sk->sleep = &vcc->sleep;
-+
-+      sk->destruct = vcc_destruct;
-       sock->sk = sk;
-       return 0;
- }
--void atm_release_vcc_sk(struct sock *sk,int free_sk)
-+void vcc_destroy_socket(struct sock *sk)
- {
--      struct atm_vcc *vcc;
-+      struct atm_vcc *vcc = atm_sk(sk);
-+      struct atm_dev *dev = vcc->dev;
-       struct sk_buff *skb;
--      vcc = sk->protinfo.af_atm;
-       clear_bit(ATM_VF_READY,&vcc->flags);
--      if (vcc->dev) {
--              if (vcc->dev->ops->close) vcc->dev->ops->close(vcc);
-+      if (dev) {
-+              if (dev->ops->close) dev->ops->close(vcc);
-               if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */
-+
-+              vcc_remove_socket(dev, sk);     /* no more receive */
-+
-               while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
-                       atm_return(vcc,skb->truesize);
--                      if (vcc->dev->ops->free_rx_skb)
--                              vcc->dev->ops->free_rx_skb(vcc,skb);
--                      else kfree_skb(skb);
-+                      kfree_skb(skb);
-               }
--              spin_lock (&atm_dev_lock);      
--              fops_put (vcc->dev->ops);
--              if (atomic_read(&vcc->sk->rmem_alloc))
--                      printk(KERN_WARNING "atm_release_vcc: strange ... "
--                          "rmem_alloc == %d after closing\n",
--                          atomic_read(&vcc->sk->rmem_alloc));
--              bind_vcc(vcc,NULL);
--      } else
--              spin_lock (&atm_dev_lock);      
--      if (free_sk) free_atm_vcc_sk(sk);
-+              fops_put (dev->ops);
-+              atm_dev_release(dev);
-+      }
--      spin_unlock (&atm_dev_lock);
-+      sock_put(sk);
- }
--
--int atm_release(struct socket *sock)
-+int vcc_release(struct socket *sock)
- {
--      if (sock->sk)
--              atm_release_vcc_sk(sock->sk,1);
-+      struct sock *sk = sock->sk;
-+      if (sk) {
-+              vcc_destroy_socket(sk);
-+      }
-       return 0;
- }
-@@ -212,7 +232,105 @@
- }
--static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
-+static int check_ci(struct atm_dev *dev, struct atm_vcc *vcc, short vpi, int vci)
-+{
-+      struct atm_vcc *walk;
-+      struct sock *s;
-+
-+      for(s = vcc_sklist; s; s = s->next) {
-+              walk = atm_sk(s);
-+              if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->dev == dev && 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 &&
-+                  vcc->qos.rxtp.traffic_class != ATM_NONE))) {
-+                      return -EADDRINUSE;
-+              }
-+              /* allow VCCs with same VPI/VCI iff they don't collide on
-+                 TX/RX (but we may refuse such sharing for other reasons,
-+                 e.g. if protocol requires to have both channels) */
-+      }
-+      return 0;
-+}
-+
-+
-+static int claim_ci(struct atm_dev *dev, struct atm_vcc *vcc, short *vpi, int *vci)
-+{
-+      static short p = 0; /* poor man's per-device cache */
-+      static int c = 0;
-+      short old_p;
-+      int old_c;
-+      int error;
-+
-+      if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY) {
-+              error = check_ci(dev, vcc, *vpi, *vci);
-+              return error;
-+      }
-+      /* last scan may have left values out of bounds for current device */
-+      if (*vpi != ATM_VPI_ANY) p = *vpi;
-+      else if (p >= 1 << dev->ci_range.vpi_bits) p = 0;
-+      if (*vci != ATM_VCI_ANY) c = *vci;
-+      else if (c < ATM_NOT_RSV_VCI || c >= 1 << dev->ci_range.vci_bits)
-+                      c = ATM_NOT_RSV_VCI;
-+      old_p = p;
-+      old_c = c;
-+      do {
-+              if (!check_ci(dev, vcc, p, c)) {
-+                      *vpi = p;
-+                      *vci = c;
-+                      return 0;
-+              }
-+              if (*vci == ATM_VCI_ANY) {
-+                      c++;
-+                      if (c >= 1 << dev->ci_range.vci_bits)
-+                              c = ATM_NOT_RSV_VCI;
-+              }
-+              if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
-+                  *vpi == ATM_VPI_ANY) {
-+                      p++;
-+                      if (p >= 1 << dev->ci_range.vpi_bits) p = 0;
-+              }
-+      }
-+      while (old_p != p || old_c != c);
-+      return -EADDRINUSE;
-+}
-+
-+
-+static void __vcc_insert_socket(struct atm_dev *dev, struct sock *sk)
-+{
-+      atm_sk(sk)->dev = dev;
-+      sk->next = vcc_sklist;
-+      if (sk->next)
-+              vcc_sklist->pprev = &sk->next;
-+      vcc_sklist = sk;
-+      sk->pprev = &vcc_sklist;
-+}
-+
-+
-+void vcc_insert_socket(struct atm_dev *dev, struct sock *sk)
-+{
-+      write_lock_irq(&vcc_sklist_lock);
-+      __vcc_insert_socket(dev, sk);
-+      write_unlock_irq(&vcc_sklist_lock);
-+}
-+EXPORT_SYMBOL(vcc_insert_socket);
-+
-+
-+void vcc_remove_socket(struct atm_dev *dev, struct sock *sk)
-+{
-+      write_lock_irq(&vcc_sklist_lock);
-+      if (sk->pprev) {
-+              if (sk->next)
-+                      sk->next->pprev = sk->pprev;
-+              *sk->pprev = sk->next;
-+              sk->pprev = NULL;
-+      }
-+      write_unlock_irq(&vcc_sklist_lock);
-+}
-+EXPORT_SYMBOL(vcc_remove_socket);
-+
-+
-+static int atm_connect_dev(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
-     int vci)
- {
-       int error;
-@@ -223,8 +341,16 @@
-               return -EINVAL;
-       if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
-               return -EPERM;
--      error = 0;
--      bind_vcc(vcc,dev);
-+      write_lock_irq(&vcc_sklist_lock);
-+      error = claim_ci(dev, vcc, &vpi, &vci);
-+      if (error) {
-+              write_unlock_irq(&vcc_sklist_lock);
-+              return error;
-+      }
-+      vcc->vpi = vpi;
-+      vcc->vci = vci;
-+      __vcc_insert_socket(dev, vcc->sk);
-+      write_unlock_irq(&vcc_sklist_lock);
-       switch (vcc->qos.aal) {
-               case ATM_AAL0:
-                       error = atm_init_aal0(vcc);
-@@ -248,7 +374,7 @@
-       if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal);
-       if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal);
-       if (error) {
--              bind_vcc(vcc,NULL);
-+              vcc_remove_socket(dev, vcc->sk);
-               return error;
-       }
-       DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal);
-@@ -256,43 +382,24 @@
-           vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
-       DPRINTK("  RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
-           vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
--      fops_get (dev->ops);
-+      if (dev->ops->owner) try_inc_mod_count(dev->ops->owner);
-       if (dev->ops->open) {
-               error = dev->ops->open(vcc,vpi,vci);
-               if (error) {
--                      fops_put (dev->ops);
--                      bind_vcc(vcc,NULL);
-+                      if (dev->ops->owner) __MOD_DEC_USE_COUNT(dev->ops->owner);
-+                      vcc_remove_socket(dev, vcc->sk);
-                       return error;
-               }
-       }
-       return 0;
- }
--
--static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
--{
--      struct atm_dev *dev;
--      int return_val;
--
--      spin_lock (&atm_dev_lock);
--      dev = atm_find_dev(itf);
--      if (!dev)
--              return_val =  -ENODEV;
--      else
--              return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
--
--      spin_unlock (&atm_dev_lock);
--
--      return return_val;
--}
--
--
- int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
- {
-       if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
-               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; "
-+      DPRINTK("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,
-           vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
-@@ -306,21 +413,28 @@
-               return -EINVAL;
-       if (itf != ATM_ITF_ANY) {
-               int error;
-+              struct atm_dev *dev;
--              error = atm_do_connect(vcc,itf,vpi,vci);
--              if (error) return error;
--      }
--      else {
-+              dev = atm_dev_lookup(itf);
-+              if (!dev) return -ENODEV;
-+
-+              error = atm_connect_dev(vcc,dev,vpi,vci);
-+              if (error) {
-+                      atm_dev_release(dev);
-+                      return error;
-+              }
-+      } else {
-               struct atm_dev *dev = NULL;
--              struct list_head *p;
-+              struct list_head *p, *next;
--              spin_lock (&atm_dev_lock);
--              list_for_each(p, &atm_devs) {
-+              list_for_each_safe(p, next, &atm_devs) {
-                       dev = list_entry(p, struct atm_dev, dev_list);
--                      if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
-+                                                      /* i suppose it could race in here CHAS */
-+                      atm_dev_hold(dev);
-+                      if (!atm_connect_dev(vcc,dev,vpi,vci)) break;
-+                      atm_dev_release(dev);
-                       dev = NULL;
-               }
--              spin_unlock (&atm_dev_lock);
-               if (!dev) return -ENODEV;
-       }
-       if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
-@@ -397,31 +511,8 @@
-                   (unsigned long) buff,eff_len);
-       DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->sk->rmem_alloc),skb->truesize);
-       atm_return(vcc,skb->truesize);
--      if (ATM_SKB(skb)->iovcnt) { /* @@@ hack */
--              /* iovcnt set, use scatter-gather for receive */
--              int el, cnt;
--              struct iovec *iov = (struct iovec *)skb->data;
--              unsigned char *p = (unsigned char *)buff;
--
--              el = eff_len;
--              error = 0;
--              for (cnt = 0; (cnt < ATM_SKB(skb)->iovcnt) && el; cnt++) {
--/*printk("s-g???: %p -> %p (%d)\n",iov->iov_base,p,iov->iov_len);*/
--                      error = copy_to_user(p,iov->iov_base,
--                          (iov->iov_len > el) ? el : iov->iov_len) ?
--                          -EFAULT : 0;
--                      if (error) break;
--                      p += iov->iov_len;
--                      el -= (iov->iov_len > el)?el:iov->iov_len;
--                      iov++;
--              }
--              if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
--              else vcc->dev->ops->free_rx_skb(vcc, skb);
--              return error ? error : eff_len;
--      }
-       error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0;
--      if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
--      else vcc->dev->ops->free_rx_skb(vcc, skb);
-+      kfree_skb(skb);
-       return error ? error : eff_len;
- }
-@@ -453,7 +544,7 @@
-       add_wait_queue(&vcc->sleep,&wait);
-       set_current_state(TASK_INTERRUPTIBLE);
-       error = 0;
--      while (!(skb = vcc->alloc_tx(vcc,eff))) {
-+      while (!(skb = alloc_tx(vcc,eff))) {
-               if (m->msg_flags & MSG_DONTWAIT) {
-                       error = -EAGAIN;
-                       break;
-@@ -478,7 +569,6 @@
-       remove_wait_queue(&vcc->sleep,&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;
-       if (copy_from_user(skb_put(skb,size),buff,size)) {
-               kfree_skb(skb);
-@@ -498,15 +588,14 @@
-       vcc = ATM_SD(sock);
-       poll_wait(file,&vcc->sleep,wait);
-       mask = 0;
--      if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq))
-+      if (skb_peek(&vcc->sk->receive_queue))
-               mask |= POLLIN | POLLRDNORM;
-       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->sk->wmem_alloc)+
--                  ATM_PDU_OVHD <= vcc->sk->sndbuf)
-+                  vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc) <= vcc->sk->sndbuf)
-                       mask |= POLLOUT | POLLWRNORM;
-       }
-       else if (vcc->reply != WAITING) {
-@@ -555,7 +644,7 @@
- int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
- {
--      struct atm_dev *dev;
-+      struct atm_dev *dev = NULL;
-       struct list_head *p;
-       struct atm_vcc *vcc;
-       int *tmp_buf, *tmp_p;
-@@ -563,7 +652,6 @@
-       int error,len,size,number, ret_val;
-       ret_val = 0;
--      spin_lock (&atm_dev_lock);
-       vcc = ATM_SD(sock);
-       switch (cmd) {
-               case SIOCOUTQ:
-@@ -581,7 +661,7 @@
-                               goto done;
-                       }
-                       ret_val =  put_user(vcc->sk->sndbuf-
--                          atomic_read(&vcc->sk->wmem_alloc)-ATM_PDU_OVHD,
-+                          atomic_read(&vcc->sk->wmem_alloc),
-                           (int *) arg) ? -EFAULT : 0;
-                       goto done;
-               case SIOCINQ:
-@@ -601,13 +689,14 @@
-                               goto done;
-                       }
-                       size = 0;
-+                      read_lock(&atm_dev_lock);
-                       list_for_each(p, &atm_devs)
-                               size += sizeof(int);
-                       if (size > len) {
-                               ret_val = -E2BIG;
-                               goto done;
-                       }
--                      tmp_buf = kmalloc(size,GFP_KERNEL);
-+                      tmp_buf = kmalloc(size, GFP_ATOMIC);
-                       if (!tmp_buf) {
-                               ret_val = -ENOMEM;
-                               goto done;
-@@ -617,6 +706,8 @@
-                               dev = list_entry(p, struct atm_dev, dev_list);
-                               *tmp_p++ = dev->number;
-                       }
-+                      read_unlock(&atm_dev_lock);
-+                      dev = NULL;
-                       ret_val = ((copy_to_user(buf, tmp_buf, size)) ||
-                           put_user(size, &((struct atm_iobuf *) arg)->length)
-                           ) ? -EFAULT : 0;
-@@ -654,39 +745,50 @@
-                       if (!error) sock->state = SS_CONNECTED;
-                       ret_val = error;
-                       goto done;
--#ifdef CONFIG_ATM_CLIP
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-               case SIOCMKCLIP:
-                       if (!capable(CAP_NET_ADMIN))
-                               ret_val = -EPERM;
-                       else 
--                              ret_val = clip_create(arg);
-+                              ret_val = atm_clip_ops->clip_create(arg);
-                       goto done;
-               case ATMARPD_CTRL:
-                       if (!capable(CAP_NET_ADMIN)) {
-                               ret_val = -EPERM;
-                               goto done;
-                       }
--                      error = atm_init_atmarp(vcc);
--                      if (!error) sock->state = SS_CONNECTED;
-+#if defined(CONFIG_ATM_CLIP_MODULE)
-+                      if (atm_clip_ops == NULL)
-+                              request_module("clip");
-+#endif
-+                      if (atm_clip_ops && !try_inc_mod_count(atm_clip_ops->owner)) {
-+                              ret_val = -ENOSYS;
-+                              goto done;
-+                      }
-+                      error = atm_clip_ops->atm_init_atmarp(vcc);
-+                      if (!error)
-+                              sock->state = SS_CONNECTED;
-+                      else
-+                              __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
-                       ret_val = error;
-                       goto done;
-               case ATMARP_MKIP:
-                       if (!capable(CAP_NET_ADMIN)) 
-                               ret_val = -EPERM;
-                       else 
--                              ret_val = clip_mkip(vcc,arg);
-+                              ret_val = atm_clip_ops->clip_mkip(vcc,arg);
-                       goto done;
-               case ATMARP_SETENTRY:
-                       if (!capable(CAP_NET_ADMIN)) 
-                               ret_val = -EPERM;
-                       else
--                              ret_val = clip_setentry(vcc,arg);
-+                              ret_val = atm_clip_ops->clip_setentry(vcc,arg);
-                       goto done;
-               case ATMARP_ENCAP:
-                       if (!capable(CAP_NET_ADMIN)) 
-                               ret_val = -EPERM;
-                       else
--                              ret_val = clip_encap(vcc,arg);
-+                              ret_val = atm_clip_ops->clip_encap(vcc,arg);
-                       goto done;
- #endif
- #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-@@ -695,27 +797,32 @@
-                               ret_val = -EPERM;
-                               goto done;
-                       }
--                        if (atm_lane_ops.lecd_attach == NULL)
--                              atm_lane_init();
--                        if (atm_lane_ops.lecd_attach == NULL) { /* try again */
-+#if defined(CONFIG_ATM_LANE_MODULE)
-+                        if (atm_lane_ops == NULL)
-+                              request_module("lec");
-+#endif
-+                        if (atm_lane_ops && !try_inc_mod_count(atm_lane_ops->owner)) {
-                               ret_val = -ENOSYS;
-                               goto done;
-                       }
--                      error = atm_lane_ops.lecd_attach(vcc, (int)arg);
--                      if (error >= 0) sock->state = SS_CONNECTED;
-+                      error = atm_lane_ops->lecd_attach(vcc, (int)arg);
-+                      if (error >= 0)
-+                              sock->state = SS_CONNECTED;
-+                      else
-+                              __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
-                       ret_val =  error;
-                       goto done;
-                 case ATMLEC_MCAST:
-                       if (!capable(CAP_NET_ADMIN))
-                               ret_val = -EPERM;
-                       else
--                              ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
-+                              ret_val = atm_lane_ops->mcast_attach(vcc, (int)arg);
-                       goto done;
-                 case ATMLEC_DATA:
-                       if (!capable(CAP_NET_ADMIN))
-                               ret_val = -EPERM;
-                       else
--                              ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
-+                              ret_val = atm_lane_ops->vcc_attach(vcc, (void*)arg);
-                       goto done;
- #endif
- #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
-@@ -724,21 +831,26 @@
-                               ret_val = -EPERM;
-                               goto done;
-                       }
--                      if (atm_mpoa_ops.mpoad_attach == NULL)
--                                atm_mpoa_init();
--                      if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
-+#if defined(CONFIG_ATM_MPOA_MODULE)
-+                      if (atm_mpoa_ops == NULL)
-+                                request_module("mpoa");
-+#endif
-+                      if (atm_mpoa_ops && !try_inc_mod_count(atm_mpoa_ops->owner)) {
-                               ret_val = -ENOSYS;
-                               goto done;
-                       }
--                      error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
--                      if (error >= 0) sock->state = SS_CONNECTED;
-+                      error = atm_mpoa_ops->mpoad_attach(vcc, (int)arg);
-+                      if (error >= 0)
-+                              sock->state = SS_CONNECTED;
-+                      else
-+                              __MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
-                       ret_val = error;
-                       goto done;
-               case ATMMPC_DATA:
-                       if (!capable(CAP_NET_ADMIN)) 
-                               ret_val = -EPERM;
-                       else
--                              ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
-+                              ret_val = atm_mpoa_ops->vcc_attach(vcc, arg);
-                       goto done;
- #endif
- #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
-@@ -747,14 +859,14 @@
-                               ret_val = -EPERM;
-                               goto done;
-                       }
--                      if (!atm_tcp_ops.attach) {
-+                      if (!atm_tcp_ops) {
-                               ret_val = -ENOPKG;
-                               goto done;
-                       }
--                      fops_get (&atm_tcp_ops);
--                      error = atm_tcp_ops.attach(vcc,(int) arg);
-+                      fops_get(atm_tcp_ops);
-+                      error = atm_tcp_ops->attach(vcc,(int) arg);
-                       if (error >= 0) sock->state = SS_CONNECTED;
--                      else            fops_put (&atm_tcp_ops);
-+                      else            fops_put(atm_tcp_ops);
-                       ret_val = error;
-                       goto done;
-               case ATMTCP_CREATE:
-@@ -762,12 +874,12 @@
-                               ret_val = -EPERM;
-                               goto done;
-                       }
--                      if (!atm_tcp_ops.create_persistent) {
-+                      if (!atm_tcp_ops) {
-                               ret_val = -ENOPKG;
-                               goto done;
-                       }
--                      error = atm_tcp_ops.create_persistent((int) arg);
--                      if (error < 0) fops_put (&atm_tcp_ops);
-+                      error = atm_tcp_ops->create_persistent((int) arg);
-+                      if (error < 0) fops_put(atm_tcp_ops);
-                       ret_val = error;
-                       goto done;
-               case ATMTCP_REMOVE:
-@@ -775,12 +887,12 @@
-                               ret_val = -EPERM;
-                               goto done;
-                       }
--                      if (!atm_tcp_ops.remove_persistent) {
-+                      if (!atm_tcp_ops) {
-                               ret_val = -ENOPKG;
-                               goto done;
-                       }
--                      error = atm_tcp_ops.remove_persistent((int) arg);
--                      fops_put (&atm_tcp_ops);
-+                      error = atm_tcp_ops->remove_persistent((int) arg);
-+                      fops_put(atm_tcp_ops);
-                       ret_val = error;
-                       goto done;
- #endif
-@@ -814,7 +926,7 @@
-               ret_val = -EFAULT;
-               goto done;
-       }
--      if (!(dev = atm_find_dev(number))) {
-+      if (!(dev = atm_dev_lookup(number))) {
-               ret_val = -ENODEV;
-               goto done;
-       }
-@@ -963,7 +1075,7 @@
-               ret_val = 0;
-  done:
--      spin_unlock (&atm_dev_lock); 
-+      if (dev) atm_dev_release(dev);
-       return ret_val;
- }
-@@ -1034,17 +1146,21 @@
-       switch (optname) {
-               case SO_ATMQOS:
-                       {
--                              struct atm_qos qos;
-+                              struct atm_qos *qos;
--                              if (copy_from_user(&qos,optval,sizeof(qos)))
-+                              qos = kmalloc(sizeof(*qos), GFP_KERNEL);
-+                              if (!qos)
-+                                      return -ENOMEM;
-+                              if (copy_from_user(qos,optval,sizeof(*qos)))
-                                       return -EFAULT;
--                              error = check_qos(&qos);
-+                              error = check_qos(qos);
-                               if (error) return error;
-                               if (sock->state == SS_CONNECTED)
--                                      return atm_change_qos(vcc,&qos);
-+                                      return atm_change_qos(vcc,qos);
-                               if (sock->state != SS_UNCONNECTED)
-                                       return -EBADFD;
--                              vcc->qos = qos;
-+                              vcc->qos = *qos;
-+                              kfree(qos);
-                               set_bit(ATM_VF_HASQOS,&vcc->flags);
-                               return 0;
-                       }
-@@ -1122,40 +1238,6 @@
- }
--/*
-- * lane_mpoa_init.c: A couple of helper functions
-- * to make modular LANE and MPOA client easier to implement
-- */
--
--/*
-- * This is how it goes:
-- *
-- * if xxxx is not compiled as module, call atm_xxxx_init_ops()
-- *    from here
-- * else call atm_mpoa_init_ops() from init_module() within
-- *    the kernel when xxxx module is loaded
-- *
-- * In either case function pointers in struct atm_xxxx_ops
-- * are initialized to their correct values. Either they
-- * point to functions in the module or in the kernel
-- */
-- 
--extern struct atm_mpoa_ops atm_mpoa_ops; /* in common.c */
--extern struct atm_lane_ops atm_lane_ops; /* in common.c */
--
--#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
--void atm_mpoa_init(void)
--{
--#ifndef CONFIG_ATM_MPOA_MODULE /* not module */
--        atm_mpoa_init_ops(&atm_mpoa_ops);
--#else
--      request_module("mpoa");
--#endif
--
--        return;
--}
--#endif
--
- #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
-@@ -1166,15 +1248,33 @@
- EXPORT_SYMBOL(br_fdb_put_hook);
- #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
- #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
-+#endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
-+
--void atm_lane_init(void)
-+static int __init atm_init(void)
- {
--#ifndef CONFIG_ATM_LANE_MODULE /* not module */
--        atm_lane_init_ops(&atm_lane_ops);
--#else
--      request_module("lec");
-+      int error = 0;
-+
-+      if (atmpvc_init() < 0)
-+              return -1;
-+      if (atmsvc_init() < 0)
-+              return -1;
-+#ifdef CONFIG_PROC_FS
-+        error = atm_proc_init();
-+        if (error) printk("atm_proc_init fails with %d\n",error);
- #endif
-+      return error;
-+}
--        return;
--}        
-+static void __exit atm_exit(void)
-+{
-+#ifdef CONFIG_PROC_FS
-+      atm_proc_exit();
- #endif
-+      atmsvc_exit();
-+      atmpvc_exit();
-+}
-+
-+module_init(atm_init);
-+module_exit(atm_exit);
-+MODULE_LICENSE("GPL");
-diff -urN linux-2.4.20/net/atm/common.h linux-2.4.20-atm/net/atm/common.h
---- linux-2.4.20/net/atm/common.h      Mon Dec 11 22:33:43 2000
-+++ linux-2.4.20-atm/net/atm/common.h  Wed May 28 01:58:41 2003
-@@ -10,8 +10,8 @@
- #include <linux/poll.h> /* for poll_table */
--int atm_create(struct socket *sock,int protocol,int family);
--int atm_release(struct socket *sock);
-+int vcc_create(struct socket *sock,int protocol,int family);
-+int vcc_release(struct socket *sock);
- 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);
-@@ -25,10 +25,17 @@
-     int *optlen);
- int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci);
--void atm_release_vcc_sk(struct sock *sk,int free_sk);
-+
- void atm_shutdown_dev(struct atm_dev *dev);
-+int atmsvc_init(void);
-+void atmsvc_exit(void);
-+
-+int atmpvc_init(void);
-+void atmpvc_exit(void);
-+
- int atm_proc_init(void);
-+void atm_proc_exit(void);
- /* SVC */
-diff -urN linux-2.4.20/net/atm/ipcommon.c linux-2.4.20-atm/net/atm/ipcommon.c
---- linux-2.4.20/net/atm/ipcommon.c    Fri Jul  7 06:37:24 2000
-+++ linux-2.4.20-atm/net/atm/ipcommon.c        Wed May 28 01:58:41 2003
-@@ -66,5 +66,5 @@
-       spin_unlock_irqrestore(&from->lock,flags);
- }
--
-+EXPORT_SYMBOL(llc_oui);
- EXPORT_SYMBOL(skb_migrate);
-diff -urN linux-2.4.20/net/atm/ipcommon.h linux-2.4.20-atm/net/atm/ipcommon.h
---- linux-2.4.20/net/atm/ipcommon.h    Mon Dec 11 22:33:46 2000
-+++ linux-2.4.20-atm/net/atm/ipcommon.h        Wed May 28 01:58:41 2003
-@@ -13,8 +13,6 @@
- #include <linux/atmdev.h>
--extern struct net_device *clip_devs;
--
- /*
-  * Appends all skbs from "from" to "to". The operation is atomic with respect
-  * to all other skb operations on "from" or "to".
-diff -urN linux-2.4.20/net/atm/lec.c linux-2.4.20-atm/net/atm/lec.c
---- linux-2.4.20/net/atm/lec.c Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/lec.c     Wed May 28 02:12:42 2003
-@@ -20,6 +20,7 @@
- #include <net/arp.h>
- #include <net/dst.h>
- #include <linux/proc_fs.h>
-+#include <linux/spinlock.h>
- /* TokenRing if needed */
- #ifdef CONFIG_TR
-@@ -35,6 +36,10 @@
- #include <linux/if_bridge.h>
- #include "../bridge/br_private.h"
- static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
-+
-+extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
-+       unsigned char *addr);
-+extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
- #endif
- /* Modular too */
-@@ -43,7 +48,7 @@
- #include "lec.h"
- #include "lec_arpc.h"
--#include "resources.h"  /* for bind_vcc() */
-+#include "resources.h"
- #if 0
- #define DPRINTK printk
-@@ -51,10 +56,7 @@
- #define DPRINTK(format,args...)
- #endif
--extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
--      unsigned char *addr);
--extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
--
-+static spinlock_t lec_arp_spinlock = SPIN_LOCK_UNLOCKED;
- #define DUMP_PACKETS 0 /* 0 = None,
-                         * 1 = 30 first bytes
-@@ -196,6 +198,22 @@
-         return 0;
- }
-+static __inline__ void
-+lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
-+{
-+      if (atm_may_send(vcc, skb->len)) {
-+              atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
-+              ATM_SKB(skb)->vcc = vcc;
-+              ATM_SKB(skb)->atm_options = vcc->atm_options;
-+              priv->stats.tx_packets++;
-+              priv->stats.tx_bytes += skb->len;
-+              vcc->send(vcc, skb);
-+      } else {
-+              priv->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+      }
-+}
-+
- static int 
- lec_send_packet(struct sk_buff *skb, struct net_device *dev)
- {
-@@ -340,34 +358,10 @@
-                 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
-                         lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
-                         lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
--                ATM_SKB(skb2)->vcc = send_vcc;
--                ATM_SKB(skb2)->iovcnt = 0;
--                ATM_SKB(skb2)->atm_options = send_vcc->atm_options;
--                DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name,
--                        send_vcc->vpi, send_vcc->vci);       
--                if (atm_may_send(send_vcc, skb2->len)) {
--                      atomic_add(skb2->truesize, &send_vcc->sk->wmem_alloc);
--                        priv->stats.tx_packets++;
--                        priv->stats.tx_bytes += skb2->len;
--                        send_vcc->send(send_vcc, skb2);
--                } else {
--                        priv->stats.tx_dropped++;
--                        dev_kfree_skb(skb2);
--              }
-+              lec_send(send_vcc, skb2, priv);
-         }
--        ATM_SKB(skb)->vcc = send_vcc;
--        ATM_SKB(skb)->iovcnt = 0;
--        ATM_SKB(skb)->atm_options = send_vcc->atm_options;
--        if (atm_may_send(send_vcc, skb->len)) {
--                atomic_add(skb->truesize, &send_vcc->sk->wmem_alloc);
--                priv->stats.tx_packets++;
--                priv->stats.tx_bytes += skb->len;
--                send_vcc->send(send_vcc, skb);
--        } else {
--                priv->stats.tx_dropped++;
--                dev_kfree_skb(skb);
--      }
-+      lec_send(send_vcc, skb, priv);
- #if 0
-         /* Should we wait for card's device driver to notify us? */
-@@ -404,7 +398,7 @@
-         int i;
-         char *tmp; /* FIXME */
--      atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
-+      atomic_sub(skb->truesize, &vcc->sk->wmem_alloc);
-         mesg = (struct atmlec_msg *)skb->data;
-         tmp = skb->data;
-         tmp += sizeof(struct atmlec_msg);
-@@ -548,24 +542,19 @@
-         }
-   
-       printk("%s: Shut down!\n", dev->name);
--        MOD_DEC_USE_COUNT;
-+      __MOD_DEC_USE_COUNT(THIS_MODULE);
- }
- static struct atmdev_ops lecdev_ops = {
--        close:        lec_atm_close,
--        send: lec_atm_send
-+        .close        = lec_atm_close,
-+        .send = lec_atm_send
- };
- static struct atm_dev lecatm_dev = {
--        &lecdev_ops,
--        NULL,     /*PHY*/
--        "lec",            /*type*/
--        999,      /*dummy device number*/
--        NULL,NULL,  /*no VCCs*/
--        NULL,NULL,  /*no data*/
--        { 0 },            /*no flags*/
--        NULL,     /* no local address*/
--        { 0 }     /*no ESI or rest of the atm_dev struct things*/
-+        .ops =                        &lecdev_ops,
-+      .type =                 "lec",
-+      .number =               999,
-+      .lock =                 SPIN_LOCK_UNLOCKED,
- };
- /*
-@@ -726,6 +723,7 @@
-                 skb->protocol = eth_type_trans(skb, dev);
-                 priv->stats.rx_packets++;
-                 priv->stats.rx_bytes += skb->len;
-+              memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
-                 netif_rx(skb);
-         }
- }
-@@ -812,7 +810,7 @@
-         lec_arp_init(priv);
-       priv->itfnum = i;  /* LANE2 addition */
-         priv->lecd = vcc;
--        bind_vcc(vcc, &lecatm_dev);
-+        vcc_insert_socket(&lecatm_dev, vcc->sk);
-         
-         vcc->proto_data = dev_lec[i];
-       set_bit(ATM_VF_META,&vcc->flags);
-@@ -833,27 +831,23 @@
-         if (dev_lec[i]->flags & IFF_UP) {
-                 netif_start_queue(dev_lec[i]);
-         }
--        MOD_INC_USE_COUNT;
-         return i;
- }
--void atm_lane_init_ops(struct atm_lane_ops *ops)
--{
--        ops->lecd_attach = lecd_attach;
--        ops->mcast_attach = lec_mcast_attach;
--        ops->vcc_attach = lec_vcc_attach;
--        ops->get_lecs = get_dev_lec;
--
--        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
--
--      return;
--}
-+static struct atm_lane_ops __atm_lane_ops = {
-+        .lecd_attach =        lecd_attach,
-+        .mcast_attach =       lec_mcast_attach,
-+        .vcc_attach = lec_vcc_attach,
-+        .get_lecs =   get_dev_lec,
-+        .owner =      THIS_MODULE
-+};
- static int __init lane_module_init(void)
- {
--        extern struct atm_lane_ops atm_lane_ops;
-+        extern struct atm_lane_ops *atm_lane_ops;
--        atm_lane_init_ops(&atm_lane_ops);
-+        atm_lane_ops = &__atm_lane_ops;
-+        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
-         return 0;
- }
-@@ -861,13 +855,10 @@
- static void __exit lane_module_cleanup(void)
- {
-         int i;
--        extern struct atm_lane_ops atm_lane_ops;
-+        extern struct atm_lane_ops *atm_lane_ops;
-         struct lec_priv *priv;
--        atm_lane_ops.lecd_attach = NULL;
--        atm_lane_ops.mcast_attach = NULL;
--        atm_lane_ops.vcc_attach = NULL;
--        atm_lane_ops.get_lecs = NULL;
-+        atm_lane_ops = NULL;
-         for (i = 0; i < MAX_LEC_ITF; i++) {
-                 if (dev_lec[i] != NULL) {
-@@ -880,7 +871,7 @@
-                         unregister_netdev(dev_lec[i]);
-                         kfree(dev_lec[i]);
-                         dev_lec[i] = NULL;
--                }
-+              }
-         }
-         return;                                    
-@@ -1030,7 +1021,7 @@
- #include <linux/timer.h>
- #include <asm/param.h>
- #include <asm/atomic.h>
--#include <linux/inetdevice.h>
-+#include <linux/netdevice.h>
- #include <net/route.h>
-@@ -1055,15 +1046,15 @@
- #define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
- static __inline__ void 
--lec_arp_lock(struct lec_priv *priv)
-+lec_arp_get(struct lec_priv *priv)
- {
--        atomic_inc(&priv->lec_arp_lock_var);
-+        atomic_inc(&priv->lec_arp_users);
- }
- static __inline__ void 
--lec_arp_unlock(struct lec_priv *priv)
-+lec_arp_put(struct lec_priv *priv)
- {
--        atomic_dec(&priv->lec_arp_lock_var);
-+        atomic_dec(&priv->lec_arp_users);
- }
- /*
-@@ -1114,33 +1105,33 @@
-  * LANE2: Add to the end of the list to satisfy 8.1.13
-  */
- static __inline__ void 
--lec_arp_put(struct lec_arp_table **lec_arp_tables, 
--            struct lec_arp_table *to_put)
-+lec_arp_add(struct lec_arp_table **lec_arp_tables, 
-+            struct lec_arp_table *to_add)
- {
--        unsigned short place;
-         unsigned long flags;
-+        unsigned short place;
-         struct lec_arp_table *tmp;
--        save_flags(flags);
--        cli();
-+        spin_lock_irqsave(&lec_arp_spinlock, flags);
--        place = HASH(to_put->mac_addr[ETH_ALEN-1]);
-+        place = HASH(to_add->mac_addr[ETH_ALEN-1]);
-         tmp = lec_arp_tables[place];
--        to_put->next = NULL;
-+        to_add->next = NULL;
-         if (tmp == NULL)
--                lec_arp_tables[place] = to_put;
-+                lec_arp_tables[place] = to_add;
-   
-         else {  /* add to the end */
-                 while (tmp->next)
-                         tmp = tmp->next;
--                tmp->next = to_put;
-+                tmp->next = to_add;
-         }
--        restore_flags(flags);
-+        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-+
-         DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
--                0xff&to_put->mac_addr[0], 0xff&to_put->mac_addr[1],
--                0xff&to_put->mac_addr[2], 0xff&to_put->mac_addr[3],
--                0xff&to_put->mac_addr[4], 0xff&to_put->mac_addr[5]);
-+                0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1],
-+                0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3],
-+                0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]);
- }
- /*
-@@ -1150,16 +1141,15 @@
- lec_arp_remove(struct lec_arp_table **lec_arp_tables,
-                struct lec_arp_table *to_remove)
- {
-+        unsigned long flags;
-         unsigned short place;
-         struct lec_arp_table *tmp;
--        unsigned long flags;
-         int remove_vcc=1;
--        save_flags(flags);
--        cli();
-+        spin_lock_irqsave(&lec_arp_spinlock, flags);
-         if (!to_remove) {
--                restore_flags(flags);
-+                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-                 return -1;
-         }
-         place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
-@@ -1171,7 +1161,7 @@
-                         tmp = tmp->next;
-                 }
-                 if (!tmp) {/* Entry was not found */
--                        restore_flags(flags);
-+                        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-                         return -1;
-                 }
-         }
-@@ -1197,7 +1187,9 @@
-                         lec_arp_clear_vccs(to_remove);
-         }
-         skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
--        restore_flags(flags);
-+
-+        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-+
-         DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-                 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
-                 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
-@@ -1382,12 +1374,8 @@
- lec_arp_destroy(struct lec_priv *priv)
- {
-         struct lec_arp_table *entry, *next;
--        unsigned long flags;
-         int i;
--        save_flags(flags);
--        cli();
--
-         del_timer(&priv->lec_arp_timer);
-         
-         /*
-@@ -1430,7 +1418,6 @@
-         priv->mcast_vcc = NULL;
-         memset(priv->lec_arp_tables, 0, 
-                sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE);
--        restore_flags(flags);
- }
-@@ -1447,18 +1434,18 @@
-         DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-                 mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff, 
-                 mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         place = HASH(mac_addr[ETH_ALEN-1]);
-   
-         to_return = priv->lec_arp_tables[place];
-         while(to_return) {
-                 if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         return to_return;
-                 }
-                 to_return = to_return->next;
-         }
--        lec_arp_unlock(priv);
-+        lec_arp_put(priv);
-         return NULL;
- }
-@@ -1585,11 +1572,11 @@
-         del_timer(&priv->lec_arp_timer);
-         DPRINTK("lec_arp_check_expire %p,%d\n",priv,
--                priv->lec_arp_lock_var.counter);
-+                atomic_read(&priv->lec_arp_users));
-         DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
-                 priv->lec_no_forward);
--        if (!priv->lec_arp_lock_var.counter) {
--                lec_arp_lock(priv);
-+        if (!atomic_read(&priv->lec_arp_users)) {
-+                lec_arp_get(priv);
-                 now = jiffies;
-                 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-                         for(entry = lec_arp_tables[i];entry != NULL;) {
-@@ -1627,6 +1614,10 @@
-                                            &&
-                                            time_after_eq(now, entry->timestamp+
-                                            priv->path_switching_delay)) {
-+                                              struct sk_buff *skb;
-+
-+                                              while ((skb = skb_dequeue(&entry->tx_wait)))
-+                                                      lec_send(entry->vcc, skb, entry->priv);
-                                                 entry->last_used = jiffies;
-                                                 entry->status = 
-                                                         ESI_FORWARD_DIRECT;
-@@ -1635,7 +1626,7 @@
-                                 }
-                         }
-                 }
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-         }
-         priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
-         add_timer(&priv->lec_arp_timer);
-@@ -1697,7 +1688,7 @@
-                 if (!entry) {
-                         return priv->mcast_vcc;
-                 }
--                lec_arp_put(priv->lec_arp_tables, entry);
-+                lec_arp_add(priv->lec_arp_tables, entry);
-                 /* We want arp-request(s) to be sent */
-                 entry->packets_flooded =1;
-                 entry->status = ESI_ARP_PENDING;
-@@ -1722,7 +1713,7 @@
-         struct lec_arp_table *entry, *next;
-         int i;
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         DPRINTK("lec_addr_delete\n");
-         for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-                 for(entry=priv->lec_arp_tables[i];entry != NULL; entry=next) {
-@@ -1733,11 +1724,11 @@
-                                 lec_arp_remove(priv->lec_arp_tables, entry);
-                                 kfree(entry);
-                         }
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         return 0;
-                 }
-         }
--        lec_arp_unlock(priv);
-+        lec_arp_put(priv);
-         return -1;
- }
-@@ -1762,7 +1753,7 @@
-                 return;   /* LANE2: ignore targetless LE_ARPs for which
-                            * we have no entry in the cache. 7.1.30
-                            */
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         if (priv->lec_arp_empty_ones) {
-                 entry = priv->lec_arp_empty_ones;
-                 if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
-@@ -1796,13 +1787,13 @@
-                                 entry->status = ESI_FORWARD_DIRECT;
-                                 memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
-                                 entry->last_used = jiffies;
--                                lec_arp_put(priv->lec_arp_tables, entry);
-+                                lec_arp_add(priv->lec_arp_tables, entry);
-                         }
-                         if (remoteflag)
-                                 entry->flags|=LEC_REMOTE_FLAG;
-                         else
-                                 entry->flags&=~LEC_REMOTE_FLAG;
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         DPRINTK("After update\n");
-                         dump_arp_table(priv);
-                         return;
-@@ -1812,11 +1803,11 @@
-         if (!entry) {
-                 entry = make_entry(priv, mac_addr);
-                 if (!entry) {
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         return;
-                 }
-                 entry->status = ESI_UNKNOWN;
--                lec_arp_put(priv->lec_arp_tables, entry);
-+                lec_arp_add(priv->lec_arp_tables, entry);
-                 /* Temporary, changes before end of function */
-         }
-         memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
-@@ -1851,7 +1842,7 @@
-         }
-         DPRINTK("After update2\n");
-         dump_arp_table(priv);
--        lec_arp_unlock(priv);
-+        lec_arp_put(priv);
- }
- /*
-@@ -1865,7 +1856,7 @@
-         struct lec_arp_table *entry;
-         int i, found_entry=0;
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         if (ioc_data->receive == 2) {
-                 /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
-@@ -1874,7 +1865,7 @@
-                 entry = lec_arp_find(priv, bus_mac);
-                 if (!entry) {
-                         printk("LEC_ARP: Multicast entry not found!\n");
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         return;
-                 }
-                 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
-@@ -1883,7 +1874,7 @@
- #endif
-                 entry = make_entry(priv, bus_mac);
-                 if (entry == NULL) {
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         return;
-                 }
-                 del_timer(&entry->timer);
-@@ -1892,7 +1883,7 @@
-                 entry->old_recv_push = old_push;
-                 entry->next = priv->mcast_fwds;
-                 priv->mcast_fwds = entry;
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-                 return;
-         } else if (ioc_data->receive == 1) {
-                 /* Vcc which we don't want to make default vcc, attach it
-@@ -1910,7 +1901,7 @@
-                         ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
-                 entry = make_entry(priv, bus_mac);
-                 if (entry == NULL) {
--                        lec_arp_unlock(priv);
-+                        lec_arp_put(priv);
-                         return;
-                 }
-                 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
-@@ -1923,7 +1914,7 @@
-                 add_timer(&entry->timer);
-                 entry->next = priv->lec_no_forward;
-                 priv->lec_no_forward = entry;
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-               dump_arp_table(priv);
-                 return;
-         }
-@@ -1982,7 +1973,7 @@
-                 }
-         }
-         if (found_entry) {
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-                 DPRINTK("After vcc was added\n");
-                 dump_arp_table(priv);
-                 return;
-@@ -1991,7 +1982,7 @@
-            this vcc */
-         entry = make_entry(priv, bus_mac);
-         if (!entry) {
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-                 return;
-         }
-         entry->vcc = vcc;
-@@ -2004,7 +1995,7 @@
-         entry->timer.expires = jiffies + priv->vcc_timeout_period;
-         entry->timer.function = lec_arp_expire_vcc;
-         add_timer(&entry->timer);
--        lec_arp_unlock(priv);
-+        lec_arp_put(priv);
-         DPRINTK("After vcc was added\n");
-       dump_arp_table(priv);
- }
-@@ -2020,6 +2011,10 @@
-                 for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) {
-                         if (entry->flush_tran_id == tran_id &&
-                             entry->status == ESI_FLUSH_PENDING) {
-+                              struct sk_buff *skb;
-+
-+                              while ((skb = skb_dequeue(&entry->tx_wait)))
-+                                      lec_send(entry->vcc, skb, entry->priv);
-                                 entry->status = ESI_FORWARD_DIRECT;
-                                 DPRINTK("LEC_ARP: Flushed\n");
-                         }
-@@ -2050,10 +2045,10 @@
-                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-         struct lec_arp_table *to_add;
-   
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         to_add = make_entry(priv, mac_addr);
-         if (!to_add) {
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-                 return -ENOMEM;
-         }
-         memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
-@@ -2063,8 +2058,8 @@
-         to_add->old_push = vcc->push;
-         vcc->push = lec_push;
-         priv->mcast_vcc = vcc;
--        lec_arp_put(priv->lec_arp_tables, to_add);
--        lec_arp_unlock(priv);
-+        lec_arp_add(priv->lec_arp_tables, to_add);
-+        lec_arp_put(priv);
-         return 0;
- }
-@@ -2076,7 +2071,7 @@
-         DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
-         dump_arp_table(priv);
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-                 for(entry = priv->lec_arp_tables[i];entry; entry=next) {
-                         next = entry->next;
-@@ -2138,7 +2133,7 @@
-                 entry = next;
-         }
--        lec_arp_unlock(priv);
-+        lec_arp_put(priv);
-       dump_arp_table(priv);
- }
-@@ -2146,9 +2141,9 @@
- lec_arp_check_empties(struct lec_priv *priv,
-                       struct atm_vcc *vcc, struct sk_buff *skb)
- {
-+        unsigned long flags;
-         struct lec_arp_table *entry, *prev;
-         struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
--        unsigned long flags;
-         unsigned char *src;
- #ifdef CONFIG_TR
-         struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
-@@ -2158,50 +2153,49 @@
- #endif
-         src = hdr->h_source;
--        lec_arp_lock(priv);
-+        lec_arp_get(priv);
-         entry = priv->lec_arp_empty_ones;
-         if (vcc == entry->vcc) {
--                save_flags(flags);
--                cli();
-+              spin_lock_irqsave(&lec_arp_spinlock, flags);
-                 del_timer(&entry->timer);
-                 memcpy(entry->mac_addr, src, ETH_ALEN);
-                 entry->status = ESI_FORWARD_DIRECT;
-                 entry->last_used = jiffies;
-                 priv->lec_arp_empty_ones = entry->next;
--                restore_flags(flags);
-+                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-                 /* We might have got an entry */
-                 if ((prev=lec_arp_find(priv,src))) {
-                         lec_arp_remove(priv->lec_arp_tables, prev);
-                         kfree(prev);
-                 }
--                lec_arp_put(priv->lec_arp_tables, entry);
--                lec_arp_unlock(priv);
-+                lec_arp_add(priv->lec_arp_tables, entry);
-+                lec_arp_put(priv);
-                 return;
-         }
-+        spin_lock_irqsave(&lec_arp_spinlock, flags);
-         prev = entry;
-         entry = entry->next;
-         while (entry && entry->vcc != vcc) {
--                prev= entry;
-+                prev = entry;
-                 entry = entry->next;
-         }
-         if (!entry) {
-                 DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
--                lec_arp_unlock(priv);
-+                lec_arp_put(priv);
-+                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-                 return;
-         }
--        save_flags(flags);
--        cli();
-         del_timer(&entry->timer);
-         memcpy(entry->mac_addr, src, ETH_ALEN);
-         entry->status = ESI_FORWARD_DIRECT;
-         entry->last_used = jiffies;
-         prev->next = entry->next;
--        restore_flags(flags);
-+        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
-         if ((prev = lec_arp_find(priv, src))) {
-                 lec_arp_remove(priv->lec_arp_tables,prev);
-                 kfree(prev);
-         }
--        lec_arp_put(priv->lec_arp_tables,entry);
--        lec_arp_unlock(priv);  
-+        lec_arp_add(priv->lec_arp_tables,entry);
-+        lec_arp_put(priv);  
- }
- MODULE_LICENSE("GPL");
-diff -urN linux-2.4.20/net/atm/lec.h linux-2.4.20-atm/net/atm/lec.h
---- linux-2.4.20/net/atm/lec.h Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/lec.h     Wed May 28 01:58:41 2003
-@@ -65,6 +65,7 @@
-         int (*mcast_attach)(struct atm_vcc *vcc, int arg);
-         int (*vcc_attach)(struct atm_vcc *vcc, void *arg);
-         struct net_device **(*get_lecs)(void);
-+        struct module *owner;
- };
- /*
-@@ -101,7 +102,7 @@
-            establishes multiple Multicast Forward VCCs to us. This list
-            collects all those VCCs. LANEv1 client has only one item in this
-            list. These entries are not aged out. */
--        atomic_t lec_arp_lock_var;
-+        atomic_t lec_arp_users;
-         struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
-         struct atm_vcc *lecd;
-         struct timer_list lec_arp_timer;
-@@ -155,7 +156,5 @@
-                  unsigned char *atm_addr, struct sk_buff *data);
- void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
--void atm_lane_init(void);
--void atm_lane_init_ops(struct atm_lane_ops *ops);
- #endif /* _LEC_H_ */
-diff -urN linux-2.4.20/net/atm/mpc.c linux-2.4.20-atm/net/atm/mpc.c
---- linux-2.4.20/net/atm/mpc.c Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/mpc.c     Wed May 28 02:14:40 2003
-@@ -28,7 +28,7 @@
- #include "lec.h"
- #include "mpc.h"
--#include "resources.h"  /* for bind_vcc() */
-+#include "resources.h"
- /*
-  * mpc.c: Implementation of MPOA client kernel part 
-@@ -521,7 +521,6 @@
-       }
-       atomic_add(skb->truesize, &entry->shortcut->sk->wmem_alloc);
--      ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
-       ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
-       entry->shortcut->send(entry->shortcut, skb);
-       entry->packets_fwded++;
-@@ -730,6 +729,7 @@
-       eg->packets_rcvd++;
-       mpc->eg_ops->put(eg);
-+      memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
-       netif_rx(new_skb);
-       return;
-@@ -741,18 +741,10 @@
- };
- static struct atm_dev mpc_dev = {
--      &mpc_ops,       /* device operations    */
--      NULL,           /* PHY operations       */
--      "mpc",          /* device type name     */
--      42,             /* device index (dummy) */
--      NULL,           /* VCC table            */
--      NULL,           /* last VCC             */
--      NULL,           /* per-device data      */
--      NULL,           /* private PHY data     */
--      { 0 },          /* device flags         */
--      NULL,           /* local ATM address    */
--      { 0 }           /* no ESI               */
--      /* rest of the members will be 0 */
-+      .ops =                  &mpc_ops,
-+      .type =                 "mpc",
-+      .number =               42,
-+      .lock =                 SPIN_LOCK_UNLOCKED
- };
- int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
-@@ -791,7 +783,7 @@
-       }
-       mpc->mpoad_vcc = vcc;
--      bind_vcc(vcc, &mpc_dev);
-+      vcc_insert_socket(&mpc_dev, vcc->sk);
-       set_bit(ATM_VF_META,&vcc->flags);
-       set_bit(ATM_VF_READY,&vcc->flags);
-@@ -807,7 +799,6 @@
-                       send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
-       }
--      MOD_INC_USE_COUNT;
-       return arg;
- }
-@@ -856,7 +847,7 @@
-       
-       printk("mpoa: (%s) going down\n",
-               (mpc->dev) ? mpc->dev->name : "<unknown>");
--      MOD_DEC_USE_COUNT;
-+      __MOD_DEC_USE_COUNT(THIS_MODULE);
-       return;
- }
-@@ -869,7 +860,7 @@
-       
-       struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
-       struct k_message *mesg = (struct k_message*)skb->data;
--      atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
-+      atomic_sub(skb->truesize, &vcc->sk->wmem_alloc);
-       
-       if (mpc == NULL) {
-               printk("mpoa: msg_from_mpoad: no mpc found\n");
-@@ -1398,11 +1389,17 @@
-       return;
- }
--void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
-+struct atm_mpoa_ops __atm_mpoa_ops = {
-+        .mpoad_attach =       atm_mpoa_mpoad_attach,
-+        .vcc_attach = atm_mpoa_vcc_attach,
-+        .owner =      THIS_MODULE
-+};
-+
-+static int __init atm_mpoa_init(void)
- {
--      ops->mpoad_attach = atm_mpoa_mpoad_attach;
--      ops->vcc_attach = atm_mpoa_vcc_attach;
-+      extern struct atm_mpoa_ops *atm_mpoa_ops;
-+      atm_mpoa_ops = &__atm_mpoa_ops;
- #ifdef CONFIG_PROC_FS
-       if(mpc_proc_init() != 0)
-               printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
-@@ -1412,22 +1409,12 @@
-       printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
--      return;
--}
--
--#ifdef MODULE
--int init_module(void)
--{
--      extern struct atm_mpoa_ops atm_mpoa_ops;
--
--      atm_mpoa_init_ops(&atm_mpoa_ops);
--
-       return 0;
- }
--void cleanup_module(void)
-+static void __exit atm_mpoa_cleanup(void)
- {
--      extern struct atm_mpoa_ops atm_mpoa_ops;
-+      extern struct atm_mpoa_ops *atm_mpoa_ops;
-       struct mpoa_client *mpc, *tmp;
-       struct atm_mpoa_qos *qos, *nextqos;
-       struct lec_priv *priv;
-@@ -1442,8 +1429,7 @@
-       del_timer(&mpc_timer);
-       unregister_netdevice_notifier(&mpoa_notifier);
--      atm_mpoa_ops.mpoad_attach = NULL;
--      atm_mpoa_ops.vcc_attach = NULL;
-+      atm_mpoa_ops = NULL;
-       mpc = mpcs;
-       mpcs = NULL;
-@@ -1475,8 +1461,9 @@
-               kfree(qos);
-               qos = nextqos;
-       }
--
--      return;
- }
--#endif /* MODULE */
-+
-+module_init(atm_mpoa_init);
-+module_exit(atm_mpoa_cleanup);
-+
- MODULE_LICENSE("GPL");
-diff -urN linux-2.4.20/net/atm/mpc.h linux-2.4.20-atm/net/atm/mpc.h
---- linux-2.4.20/net/atm/mpc.h Mon Dec 11 22:33:43 2000
-+++ linux-2.4.20-atm/net/atm/mpc.h     Wed May 28 01:58:41 2003
-@@ -48,11 +48,8 @@
- struct atm_mpoa_ops {
-         int (*mpoad_attach)(struct atm_vcc *vcc, int arg);  /* attach mpoa daemon  */
-         int (*vcc_attach)(struct atm_vcc *vcc, long arg);   /* attach shortcut vcc */
-+        struct module *owner;
- };
--
--/* Boot/module initialization function */
--void atm_mpoa_init(void);
--void atm_mpoa_init_ops(struct atm_mpoa_ops *ops);
- /* MPOA QoS operations */
- struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos);
-diff -urN linux-2.4.20/net/atm/pppoatm.c linux-2.4.20-atm/net/atm/pppoatm.c
---- linux-2.4.20/net/atm/pppoatm.c     Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/pppoatm.c Wed May 28 02:15:02 2003
-@@ -232,7 +232,6 @@
-               return 1;
-       }
-       atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->sk->wmem_alloc);
--      ATM_SKB(skb)->iovcnt = 0;
-       ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
-       DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
-           pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
-diff -urN linux-2.4.20/net/atm/proc.c linux-2.4.20-atm/net/atm/proc.c
---- linux-2.4.20/net/atm/proc.c        Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/proc.c    Wed May 28 02:46:02 2003
-@@ -39,16 +39,15 @@
- #include "common.h" /* atm_proc_init prototype */
- #include "signaling.h" /* to get sigd - ugly too */
--#ifdef CONFIG_ATM_CLIP
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
- #include <net/atmclip.h>
--#include "ipcommon.h"
--extern void clip_push(struct atm_vcc *vcc,struct sk_buff *skb);
-+extern struct atm_clip_ops *atm_clip_ops; /* in common.c */
- #endif
- #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- #include "lec.h"
- #include "lec_arpc.h"
--extern struct atm_lane_ops atm_lane_ops; /* in common.c */
-+extern struct atm_lane_ops *atm_lane_ops; /* in common.c */
- #endif
- static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
-@@ -85,11 +84,12 @@
-       add_stats(buf,"0",&dev->stats.aal0);
-       strcat(buf,"  ");
-       add_stats(buf,"5",&dev->stats.aal5);
-+      sprintf(strchr(buf,0), "        %d", atomic_read(&dev->refcnt));
-       strcat(buf,"\n");
- }
--#ifdef CONFIG_ATM_CLIP
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
- static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
-@@ -178,8 +178,8 @@
-           aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr,
-           class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
-           class_name[vcc->qos.txtp.traffic_class]);
--#ifdef CONFIG_ATM_CLIP
--      if (vcc->push == clip_push) {
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-+      if (atm_clip_ops && (vcc->push == atm_clip_ops->clip_push)) {
-               struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
-               struct net_device *dev;
-@@ -220,10 +220,11 @@
-               default:
-                       here += sprintf(here,"%3d",vcc->sk->family);
-       }
--      here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
-+      here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d  %d\n",vcc->flags.bits,
-           vcc->reply,
-           atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
--          atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
-+          atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf,
-+          atomic_read(&vcc->sk->refcnt));
- }
-@@ -311,26 +312,24 @@
-                   "AAL(TX,err,RX,err,drop) ...\n");
-       }
-       left = pos-1;
-+      read_lock(&atm_dev_lock);
-       list_for_each(p, &atm_devs) {
-               dev = list_entry(p, struct atm_dev, dev_list);
-               if (left-- == 0) {
-                       dev_info(dev,buf);
-+                      read_unlock(&atm_dev_lock);
-                       return strlen(buf);
-               }
-       }
-+      read_unlock(&atm_dev_lock);
-       return 0;
- }
--/*
-- * FIXME: it isn't safe to walk the VCC list without turning off interrupts.
-- * What is really needed is some lock on the devices. Ditto for ATMARP.
-- */
- static int atm_pvc_info(loff_t pos,char *buf)
- {
--      struct atm_dev *dev;
--      struct list_head *p;
-       struct atm_vcc *vcc;
-+      struct sock *s;
-       int left;
-       if (!pos) {
-@@ -338,24 +337,25 @@
-                   "TX(PCR,Class)\n");
-       }
-       left = pos-1;
--      list_for_each(p, &atm_devs) {
--              dev = list_entry(p, struct atm_dev, dev_list);
--              for (vcc = dev->vccs; vcc; vcc = vcc->next)
--                      if (vcc->sk->family == PF_ATMPVC &&
--                          vcc->dev && !left--) {
--                              pvc_info(vcc,buf);
--                              return strlen(buf);
--                      }
-+      read_lock(&vcc_sklist_lock);
-+      for(s = vcc_sklist; s; s = s->next) {
-+              vcc = atm_sk(s);
-+              if (vcc->sk->family == PF_ATMPVC &&
-+                  vcc->dev && !left--) {
-+                      pvc_info(vcc,buf);
-+                      read_unlock(&vcc_sklist_lock);
-+                      return strlen(buf);
-+              }
-       }
-+      read_unlock(&vcc_sklist_lock);
-       return 0;
- }
- static int atm_vc_info(loff_t pos,char *buf)
- {
--      struct atm_dev *dev;
--      struct list_head *p;
-       struct atm_vcc *vcc;
-+      struct sock *s;
-       int left;
-       if (!pos)
-@@ -363,19 +363,16 @@
-                   "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
-                   "     Recv buffer\n");
-       left = pos-1;
--      list_for_each(p, &atm_devs) {
--              dev = list_entry(p, struct atm_dev, dev_list);
--              for (vcc = dev->vccs; vcc; vcc = vcc->next)
--                      if (!left--) {
--                              vc_info(vcc,buf);
--                              return strlen(buf);
--                      }
--      }
--      for (vcc = nodev_vccs; vcc; vcc = vcc->next)
-+      read_lock(&vcc_sklist_lock);
-+      for(s = vcc_sklist; s; s = s->next) {
-+              vcc = atm_sk(s);
-               if (!left--) {
-                       vc_info(vcc,buf);
-+                      read_unlock(&vcc_sklist_lock);
-                       return strlen(buf);
-               }
-+      }
-+      read_unlock(&vcc_sklist_lock);
-       return 0;
- }
-@@ -383,31 +380,28 @@
- static int atm_svc_info(loff_t pos,char *buf)
- {
--      struct atm_dev *dev;
--      struct list_head *p;
-       struct atm_vcc *vcc;
-+      struct sock *s;
-       int left;
-       if (!pos)
-               return sprintf(buf,"Itf VPI VCI           State      Remote\n");
-       left = pos-1;
--      list_for_each(p, &atm_devs) {
--              dev = list_entry(p, struct atm_dev, dev_list);
--              for (vcc = dev->vccs; vcc; vcc = vcc->next)
--                      if (vcc->sk->family == PF_ATMSVC && !left--) {
--                              svc_info(vcc,buf);
--                              return strlen(buf);
--                      }
--      }
--      for (vcc = nodev_vccs; vcc; vcc = vcc->next)
-+      read_lock(&vcc_sklist_lock);
-+      for(s = vcc_sklist; s; s = s->next) {
-+              vcc = atm_sk(s);
-               if (vcc->sk->family == PF_ATMSVC && !left--) {
-                       svc_info(vcc,buf);
-+                      read_unlock(&vcc_sklist_lock);
-                       return strlen(buf);
-               }
-+      }
-+      read_unlock(&vcc_sklist_lock);
-+
-       return 0;
- }
--#ifdef CONFIG_ATM_CLIP
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
- static int atm_arp_info(loff_t pos,char *buf)
- {
-       struct neighbour *n;
-@@ -417,28 +411,30 @@
-               return sprintf(buf,"IPitf TypeEncp Idle IP address      "
-                   "ATM address\n");
-       }
-+      if (!clip_tbl_hook)
-+              return 0;
-       count = pos;
--      read_lock_bh(&clip_tbl.lock);
-+      read_lock_bh(&clip_tbl_hook->lock);
-       for (i = 0; i <= NEIGH_HASHMASK; i++)
--              for (n = clip_tbl.hash_buckets[i]; n; n = n->next) {
-+              for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) {
-                       struct atmarp_entry *entry = NEIGH2ENTRY(n);
-                       struct clip_vcc *vcc;
-                       if (!entry->vccs) {
-                               if (--count) continue;
-                               atmarp_info(n->dev,entry,NULL,buf);
--                              read_unlock_bh(&clip_tbl.lock);
-+                              read_unlock_bh(&clip_tbl_hook->lock);
-                               return strlen(buf);
-                       }
-                       for (vcc = entry->vccs; vcc;
-                           vcc = vcc->next) {
-                               if (--count) continue;
-                               atmarp_info(n->dev,entry,vcc,buf);
--                              read_unlock_bh(&clip_tbl.lock);
-+                              read_unlock_bh(&clip_tbl_hook->lock);
-                               return strlen(buf);
-                       }
-               }
--      read_unlock_bh(&clip_tbl.lock);
-+      read_unlock_bh(&clip_tbl_hook->lock);
-       return 0;
- }
- #endif
-@@ -456,10 +452,13 @@
-                   "                          Status            Flags "
-                   "VPI/VCI Recv VPI/VCI\n");
-       }
--      if (atm_lane_ops.get_lecs == NULL)
-+      if (!atm_lane_ops)
-               return 0; /* the lane module is not there yet */
--      else
--              dev_lec = atm_lane_ops.get_lecs();
-+
-+      if (!try_inc_mod_count(atm_lane_ops->owner))
-+              return 0;
-+
-+      dev_lec = atm_lane_ops->get_lecs();
-       count = pos;
-       for(d=0;d<MAX_LEC_ITF;d++) {
-@@ -472,6 +471,7 @@
-                               e=sprintf(buf,"%s ",
-                                   dev_lec[d]->name);
-                               lec_info(entry,buf+e);
-+                              __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
-                               return strlen(buf);
-                       }
-               }
-@@ -480,6 +480,7 @@
-                       if (--count) continue;
-                       e=sprintf(buf,"%s ",dev_lec[d]->name);
-                       lec_info(entry, buf+e);
-+                      __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
-                       return strlen(buf);
-               }
-               for(entry=priv->lec_no_forward; entry;
-@@ -487,6 +488,7 @@
-                       if (--count) continue;
-                       e=sprintf(buf,"%s ",dev_lec[d]->name);
-                       lec_info(entry, buf+e);
-+                      __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
-                       return strlen(buf);
-               }
-               for(entry=priv->mcast_fwds; entry;
-@@ -494,9 +496,11 @@
-                       if (--count) continue;
-                       e=sprintf(buf,"%s ",dev_lec[d]->name);
-                       lec_info(entry, buf+e);
-+                      __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
-                       return strlen(buf);
-               }
-       }
-+      __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
-       return 0;
- }
- #endif
-@@ -566,7 +570,7 @@
-       for (num = dev->number; num; num /= 10) digits++;
-       if (!digits) digits++;
--      dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_ATOMIC);
-+      dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL);
-       if (!dev->proc_name)
-               goto fail1;
-       sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
-@@ -599,12 +603,11 @@
-     name->proc_fops = &proc_spec_atm_operations; \
-     name->owner = THIS_MODULE
-+struct proc_dir_entry *devices = NULL, *pvc = NULL, *svc = NULL;
-+struct proc_dir_entry *arp = NULL, *lec = NULL, *vc = NULL;
- 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("net/atm",NULL);
-       if (!atm_proc_root)
-               return -ENOMEM;
-@@ -612,7 +615,7 @@
-       CREATE_ENTRY(pvc);
-       CREATE_ENTRY(svc);
-       CREATE_ENTRY(vc);
--#ifdef CONFIG_ATM_CLIP
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-       CREATE_ENTRY(arp);
- #endif
- #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-@@ -629,4 +632,15 @@
-       if (vc) remove_proc_entry("vc",atm_proc_root);
-       remove_proc_entry("net/atm",NULL);
-       return -ENOMEM;
-+}
-+
-+void __exit atm_proc_exit(void)
-+{
-+      if (vc) remove_proc_entry("vc",atm_proc_root);
-+      if (lec) remove_proc_entry("lec",atm_proc_root);
-+      if (arp) remove_proc_entry("arp",atm_proc_root);
-+      if (svc) remove_proc_entry("svc",atm_proc_root);
-+      if (pvc) remove_proc_entry("pvc",atm_proc_root);
-+      if (devices) remove_proc_entry("devices",atm_proc_root);
-+      remove_proc_entry("net/atm",NULL);
- }
-diff -urN linux-2.4.20/net/atm/pvc.c linux-2.4.20-atm/net/atm/pvc.c
---- linux-2.4.20/net/atm/pvc.c Thu Apr 12 21:11:39 2001
-+++ linux-2.4.20-atm/net/atm/pvc.c     Wed May 28 01:58:41 2003
-@@ -15,17 +15,10 @@
- #include <linux/skbuff.h>
- #include <linux/bitops.h>
- #include <net/sock.h>         /* for sock_no_* */
--#ifdef CONFIG_ATM_CLIP
--#include <net/atmclip.h>
--#endif
- #include "resources.h"                /* devs and vccs */
- #include "common.h"           /* common for PVCs and SVCs */
--#ifndef NULL
--#define NULL 0
--#endif
--
- static int pvc_shutdown(struct socket *sock,int how)
- {
-@@ -77,45 +70,38 @@
- }
--static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = {
--      family:         PF_ATMPVC,
-+static struct proto_ops pvc_proto_ops = {
-+      .family =       PF_ATMPVC,
--      release:        atm_release,
--      bind:           pvc_bind,
--      connect:        pvc_connect,
--      socketpair:     sock_no_socketpair,
--      accept:         sock_no_accept,
--      getname:        pvc_getname,
--      poll:           atm_poll,
--      ioctl:          atm_ioctl,
--      listen:         sock_no_listen,
--      shutdown:       pvc_shutdown,
--      setsockopt:     atm_setsockopt,
--      getsockopt:     atm_getsockopt,
--      sendmsg:        atm_sendmsg,
--      recvmsg:        atm_recvmsg,
--      mmap:           sock_no_mmap,
--      sendpage:       sock_no_sendpage,
-+      .release =      vcc_release,
-+      .bind =         pvc_bind,
-+      .connect =      pvc_connect,
-+      .socketpair =   sock_no_socketpair,
-+      .accept =       sock_no_accept,
-+      .getname =      pvc_getname,
-+      .poll =         atm_poll,
-+      .ioctl =        atm_ioctl,
-+      .listen =       sock_no_listen,
-+      .shutdown =     pvc_shutdown,
-+      .setsockopt =   atm_setsockopt,
-+      .getsockopt =   atm_getsockopt,
-+      .sendmsg =      atm_sendmsg,
-+      .recvmsg =      atm_recvmsg,
-+      .mmap =         sock_no_mmap,
-+      .sendpage =     sock_no_sendpage,
- };
--#include <linux/smp_lock.h>
--SOCKOPS_WRAP(pvc_proto, PF_ATMPVC);
--
--
- static int pvc_create(struct socket *sock,int protocol)
- {
-       sock->ops = &pvc_proto_ops;
--      return atm_create(sock,protocol,PF_ATMPVC);
-+      return vcc_create(sock,protocol,PF_ATMPVC);
- }
- static struct net_proto_family pvc_family_ops = {
--      PF_ATMPVC,
--      pvc_create,
--      0,                      /* no authentication */
--      0,                      /* no encryption */
--      0                       /* no encrypt_net */
-+      .family = PF_ATMPVC,
-+      .create = pvc_create,
- };
-@@ -124,23 +110,20 @@
-  */
--static int __init atmpvc_init(void)
-+int __init atmpvc_init(void)
- {
-       int error;
-       error = sock_register(&pvc_family_ops);
-       if (error < 0) {
--              printk(KERN_ERR "ATMPVC: can't register (%d)",error);
-+              printk(KERN_ERR "ATMPVC: can't register (%d)", error);
-               return error;
-       }
--#ifdef CONFIG_ATM_CLIP
--      atm_clip_init();
--#endif
--#ifdef CONFIG_PROC_FS
--      error = atm_proc_init();
--      if (error) printk("atm_proc_init fails with %d\n",error);
--#endif
--      return 0;
-+
-+      return error;
- }
--module_init(atmpvc_init);
-+void __exit atmpvc_exit(void)
-+{
-+      sock_unregister(PF_ATMPVC);
-+}
-diff -urN linux-2.4.20/net/atm/raw.c linux-2.4.20-atm/net/atm/raw.c
---- linux-2.4.20/net/atm/raw.c Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/raw.c     Wed May 28 01:58:41 2003
-@@ -37,7 +37,7 @@
- static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
- {
-       DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->sk->wmem_alloc,skb->truesize);
--      atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
-+      atomic_sub(skb->truesize,&vcc->sk->wmem_alloc);
-       dev_kfree_skb_any(skb);
-       wake_up(&vcc->sleep);
- }
-diff -urN linux-2.4.20/net/atm/resources.c linux-2.4.20-atm/net/atm/resources.c
---- linux-2.4.20/net/atm/resources.c   Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/resources.c       Wed May 28 02:38:44 2003
-@@ -2,7 +2,6 @@
- /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
--
- #include <linux/config.h>
- #include <linux/ctype.h>
- #include <linux/string.h>
-@@ -11,198 +10,185 @@
- #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 */
- #include "common.h"
- #include "resources.h"
--
--#ifndef NULL
--#define NULL 0
--#endif
--
-+struct sock *vcc_sklist = NULL;
-+rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED;
- LIST_HEAD(atm_devs);
--struct atm_vcc *nodev_vccs = NULL;
--extern spinlock_t atm_dev_lock;
-+rwlock_t atm_dev_lock = RW_LOCK_UNLOCKED;
--static struct atm_dev *alloc_atm_dev(const char *type)
-+static struct atm_dev *__alloc_atm_dev(const char *type)
- {
-       struct atm_dev *dev;
-       dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
--      if (!dev) return NULL;
--      memset(dev,0,sizeof(*dev));
-+      if (!dev)
-+              return NULL;
-+      memset(dev, 0, sizeof(*dev));
-       dev->type = type;
-       dev->signal = ATM_PHY_SIG_UNKNOWN;
-       dev->link_rate = ATM_OC3_PCR;
--      list_add_tail(&dev->dev_list, &atm_devs);
-+      dev->dev_data = NULL;
-+      memset(&dev->stats, 0, sizeof(dev->stats));
-+      atomic_set(&dev->refcnt, 0);
-+      spin_lock_init(&dev->lock);
-       return dev;
- }
--static void free_atm_dev(struct atm_dev *dev)
-+static void __free_atm_dev(struct atm_dev *dev)
- {
--      list_del(&dev->dev_list);
-       kfree(dev);
- }
--struct atm_dev *atm_find_dev(int number)
-+static struct atm_dev *__atm_dev_lookup(int number)
- {
-       struct atm_dev *dev;
-       struct list_head *p;
-       list_for_each(p, &atm_devs) {
-               dev = list_entry(p, struct atm_dev, dev_list);
--              if (dev->ops && dev->number == number)
-+              if (dev->ops && dev->number == number) {
-+                      atm_dev_hold(dev);
-                       return dev;
-+              }
-       }
-       return NULL;
- }
--struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
--    int number,atm_dev_flags_t *flags)
-+struct atm_dev *atm_dev_lookup(int number)
- {
--      struct atm_dev *dev = NULL;
-+      struct atm_dev *dev;
-+
-+      read_lock(&atm_dev_lock);
-+      dev = __atm_dev_lookup(number);
-+      read_unlock(&atm_dev_lock);
-+      return dev;
-+}
--      spin_lock(&atm_dev_lock);
-+void atm_dev_hold(struct atm_dev *dev)
-+{
-+      atomic_inc(&dev->refcnt);
-+}
--      dev = alloc_atm_dev(type);
-+void atm_dev_release(struct atm_dev *dev)
-+{
-+      atomic_dec(&dev->refcnt);
-+
-+      if ((atomic_read(&dev->refcnt) == 1) &&
-+          test_bit(ATM_DF_CLOSE,&dev->flags))
-+              shutdown_atm_dev(dev);
-+}
-+
-+
-+struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
-+                               int number, atm_dev_flags_t *flags)
-+{
-+      struct atm_dev *dev, *inuse;
-+
-+      dev = __alloc_atm_dev(type);
-       if (!dev) {
-               printk(KERN_ERR "atm_dev_register: no space for dev %s\n",
-                   type);
--              goto done;
-+              return NULL;
-       }
-+      write_lock(&atm_dev_lock);
-       if (number != -1) {
--              if (atm_find_dev(number)) {
--                      free_atm_dev(dev);
-+              if ((inuse = __atm_dev_lookup(number))) {
-+                      atm_dev_release(inuse);
-+                      __free_atm_dev(dev);
-+                      write_unlock(&atm_dev_lock);
-                       return NULL;
-               }
-               dev->number = number;
-       } else {
-               dev->number = 0;
--              while (atm_find_dev(dev->number)) dev->number++;
-+              while ((inuse = __atm_dev_lookup(dev->number))) {
-+                      atm_dev_release(inuse);
-+                      dev->number++;
-+              }
-       }
--      dev->vccs = dev->last = NULL;
--      dev->dev_data = NULL;
--      barrier();
-+
-       dev->ops = ops;
--      if (flags) 
-+      if (flags)
-               dev->flags = *flags;
--      else 
--              memset(&dev->flags,0,sizeof(dev->flags));
--      memset((void *) &dev->stats,0,sizeof(dev->stats));
-+      else
-+              memset(&dev->flags, 0, sizeof(dev->flags));
-+      atomic_inc(&dev->refcnt);
-+      list_add_tail(&dev->dev_list, &atm_devs);
-+      write_unlock(&atm_dev_lock);
-+      barrier();
-+
- #ifdef CONFIG_PROC_FS
--      if (ops->proc_read)
-+      if (ops->proc_read) {
-               if (atm_proc_dev_register(dev) < 0) {
-                       printk(KERN_ERR "atm_dev_register: "
--                          "atm_proc_dev_register failed for dev %s\n",type);
--                      free_atm_dev(dev);
--                      goto done;
-+                             "atm_proc_dev_register failed for dev %s\n",
-+                             type);
-+                      write_lock(&atm_dev_lock);
-+                      list_del(&dev->dev_list);
-+                      write_unlock(&atm_dev_lock);
-+                      __free_atm_dev(dev);
-+                      return NULL;
-               }
-+      }
- #endif
--done:
--      spin_unlock(&atm_dev_lock);
-       return dev;
- }
- void atm_dev_deregister(struct atm_dev *dev)
- {
-+      unsigned long warning_time;
-+
- #ifdef CONFIG_PROC_FS
--      if (dev->ops->proc_read) atm_proc_dev_deregister(dev);
-+      if (dev->ops->proc_read)
-+              atm_proc_dev_deregister(dev);
- #endif
--      spin_lock(&atm_dev_lock);
--      free_atm_dev(dev);
--      spin_unlock(&atm_dev_lock);
--}
--
--void shutdown_atm_dev(struct atm_dev *dev)
--{
--      if (dev->vccs) {
--              set_bit(ATM_DF_CLOSE,&dev->flags);
--              return;
--      }
--      if (dev->ops->dev_close) dev->ops->dev_close(dev);
--      atm_dev_deregister(dev);
--}
--
--
--/* Handler for sk->destruct, invoked by sk_free() */
--static void atm_free_sock(struct sock *sk)
--{
--      kfree(sk->protinfo.af_atm);
--}
--
--struct sock *alloc_atm_vcc_sk(int family)
--{
--      struct sock *sk;
--      struct atm_vcc *vcc;
--
--      sk = sk_alloc(family, GFP_KERNEL, 1);
--      if (!sk) return NULL;
--      vcc = sk->protinfo.af_atm = kmalloc(sizeof(*vcc),GFP_KERNEL);
--      if (!vcc) {
--              sk_free(sk);
--              return NULL;
--      }
--      sock_init_data(NULL,sk);
--      sk->destruct = atm_free_sock;
--      memset(vcc,0,sizeof(*vcc));
--      vcc->sk = sk;
--      if (nodev_vccs) nodev_vccs->prev = vcc;
--      vcc->prev = NULL;
--      vcc->next = nodev_vccs;
--      nodev_vccs = vcc;
--      return sk;
--}
--
--
--static void unlink_vcc(struct atm_vcc *vcc,struct atm_dev *hold_dev)
--{
--      if (vcc->prev) vcc->prev->next = vcc->next;
--      else if (vcc->dev) vcc->dev->vccs = vcc->next;
--          else nodev_vccs = vcc->next;
--      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 &&
--          test_bit(ATM_DF_CLOSE,&vcc->dev->flags))
--              shutdown_atm_dev(vcc->dev);
--}
-+      write_lock(&atm_dev_lock);
-+      list_del(&dev->dev_list);
-+      write_unlock(&atm_dev_lock);
-+        warning_time = jiffies;
-+        while (atomic_read(&dev->refcnt) != 1) {
-+                current->state = TASK_INTERRUPTIBLE;
-+                schedule_timeout(HZ / 4);
-+                current->state = TASK_RUNNING;
-+                if ((jiffies - warning_time) > 10 * HZ) {
-+                        printk(KERN_EMERG "atm_dev_deregister: waiting for "
-+                               "dev %d to become free. Usage count = %d\n",
-+                               dev->number, atomic_read(&dev->refcnt));
-+                        warning_time = jiffies;
-+                }
-+        }
--void free_atm_vcc_sk(struct sock *sk)
--{
--      unlink_vcc(sk->protinfo.af_atm,NULL);
--      sk_free(sk);
-+      __free_atm_dev(dev);
- }
--void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev)
-+void shutdown_atm_dev(struct atm_dev *dev)
- {
--      unlink_vcc(vcc,dev);
--      vcc->dev = dev;
--      if (dev) {
--              vcc->next = NULL;
--              vcc->prev = dev->last;
--              if (dev->vccs) dev->last->next = vcc;
--              else dev->vccs = vcc;
--              dev->last = vcc;
--      }
--      else {
--              if (nodev_vccs) nodev_vccs->prev = vcc;
--              vcc->next = nodev_vccs;
--              vcc->prev = NULL;
--              nodev_vccs = vcc;
-+      if (atomic_read(&dev->refcnt) > 1) {
-+              set_bit(ATM_DF_CLOSE, &dev->flags);
-+              return;
-       }
-+      if (dev->ops->dev_close)
-+              dev->ops->dev_close(dev);
-+      atm_dev_deregister(dev);
- }
- EXPORT_SYMBOL(atm_dev_register);
- EXPORT_SYMBOL(atm_dev_deregister);
--EXPORT_SYMBOL(atm_find_dev);
-+EXPORT_SYMBOL(atm_dev_lookup);
-+EXPORT_SYMBOL(atm_dev_hold);
-+EXPORT_SYMBOL(atm_dev_release);
- EXPORT_SYMBOL(shutdown_atm_dev);
--EXPORT_SYMBOL(bind_vcc);
-+EXPORT_SYMBOL(vcc_sklist);
-+EXPORT_SYMBOL(vcc_sklist_lock);
-diff -urN linux-2.4.20/net/atm/resources.h linux-2.4.20-atm/net/atm/resources.h
---- linux-2.4.20/net/atm/resources.h   Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/resources.h       Wed May 28 02:23:53 2003
-@@ -11,11 +11,7 @@
- extern struct list_head atm_devs;
--extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */
--
--
--struct sock *alloc_atm_vcc_sk(int family);
--void free_atm_vcc_sk(struct sock *sk);
-+extern rwlock_t atm_dev_lock;
- #ifdef CONFIG_PROC_FS
-diff -urN linux-2.4.20/net/atm/signaling.c linux-2.4.20-atm/net/atm/signaling.c
---- linux-2.4.20/net/atm/signaling.c   Wed May 28 01:54:25 2003
-+++ linux-2.4.20-atm/net/atm/signaling.c       Wed May 28 02:28:19 2003
-@@ -33,7 +33,6 @@
- struct atm_vcc *sigd = NULL;
- static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
--extern spinlock_t atm_dev_lock;
- static void sigd_put_skb(struct sk_buff *skb)
- {
-@@ -98,7 +97,7 @@
-       struct atm_vcc *session_vcc;
-       msg = (struct atmsvc_msg *) skb->data;
--      atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
-+      atomic_sub(skb->truesize,&vcc->sk->wmem_alloc);
-       DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
-         (unsigned long) msg->vcc);
-       vcc = *(struct atm_vcc **) &msg->vcc;
-@@ -115,7 +114,7 @@
-                       }
-                       session_vcc = vcc->session ? vcc->session : vcc;
-                       if (session_vcc->vpi || session_vcc->vci) break;
--                      session_vcc->itf = msg->pvc.sap_addr.itf;
-+                      session_vcc->sk->bound_dev_if = msg->pvc.sap_addr.itf;
-                       session_vcc->vpi = msg->pvc.sap_addr.vpi;
-                       session_vcc->vci = msg->pvc.sap_addr.vci;
-                       if (session_vcc->vpi || session_vcc->vci)
-@@ -129,12 +128,12 @@
-               case as_indicate:
-                       vcc = *(struct atm_vcc **) &msg->listen_vcc;
-                       DPRINTK("as_indicate!!!\n");
--                      if (!vcc->backlog_quota) {
-+                      if (vcc->sk->ack_backlog == vcc->sk->max_ack_backlog) {
-                               sigd_enq(0,as_reject,vcc,NULL,NULL);
-                               return 0;
-                       }
--                      vcc->backlog_quota--;
--                      skb_queue_tail(&vcc->listenq,skb);
-+                      vcc->sk->ack_backlog++;
-+                      skb_queue_tail(&vcc->sk->receive_queue,skb);
-                       if (vcc->callback) {
-                               DPRINTK("waking vcc->sleep 0x%p\n",
-                                   &vcc->sleep);
-@@ -195,16 +194,13 @@
- }
--static void purge_vccs(struct atm_vcc *vcc)
-+static void purge_vcc(struct atm_vcc *vcc)
- {
--      while (vcc) {
--              if (vcc->sk->family == PF_ATMSVC &&
--                  !test_bit(ATM_VF_META,&vcc->flags)) {
--                      set_bit(ATM_VF_RELEASED,&vcc->flags);
--                      vcc->reply = -EUNATCH;
--                      wake_up(&vcc->sleep);
--              }
--              vcc = vcc->next;
-+      if (vcc->sk->family == PF_ATMSVC &&
-+          !test_bit(ATM_VF_META,&vcc->flags)) {
-+              set_bit(ATM_VF_RELEASED,&vcc->flags);
-+              vcc->reply = -EUNATCH;
-+              wake_up(&vcc->sleep);
-       }
- }
-@@ -213,39 +209,42 @@
- {
-       struct atm_dev *dev;
-       struct list_head *p;
-+      struct sock *s;
-       DPRINTK("sigd_close\n");
-       sigd = NULL;
-       if (skb_peek(&vcc->sk->receive_queue))
-               printk(KERN_ERR "sigd_close: closing with requests pending\n");
-       skb_queue_purge(&vcc->sk->receive_queue);
--      purge_vccs(nodev_vccs);
--      spin_lock (&atm_dev_lock);
-+      read_lock(&atm_dev_lock);
-       list_for_each(p, &atm_devs) {
-               dev = list_entry(p, struct atm_dev, dev_list);
--              purge_vccs(dev->vccs);
-+
-+              read_lock(&vcc_sklist_lock);
-+              for(s = vcc_sklist; s; s = s->next) {
-+                      struct atm_vcc *vcc = atm_sk(s);
-+
-+                      if (vcc->dev == dev) purge_vcc(vcc);
-+              }
-+              read_unlock(&vcc_sklist_lock);
-       }
--      spin_unlock (&atm_dev_lock);
-+      read_unlock(&atm_dev_lock);
- }
- static struct atmdev_ops sigd_dev_ops = {
--      close:  sigd_close,
--      send:   sigd_send
-+      .close =        sigd_close,
-+      .send =         sigd_send
- };
- static struct atm_dev sigd_dev = {
--      &sigd_dev_ops,
--      NULL,           /* no PHY */
--      "sig",          /* type */
--      999,            /* dummy device number */
--      NULL,NULL,      /* pretend not to have any VCCs */
--      NULL,NULL,      /* no data */
--      { 0 },          /* no flags */
--      NULL,           /* no local address */
--      { 0 }           /* no ESI, no statistics */
-+      .ops =                  &sigd_dev_ops,
-+      .phy =                  NULL,
-+      .type =                 "sig",
-+      .number =               999,
-+      .lock =                 SPIN_LOCK_UNLOCKED
- };
-@@ -254,7 +253,7 @@
-       if (sigd) return -EADDRINUSE;
-       DPRINTK("sigd_attach\n");
-       sigd = vcc;
--      bind_vcc(vcc,&sigd_dev);
-+      vcc_insert_socket(&sigd_dev, vcc->sk);
-       set_bit(ATM_VF_META,&vcc->flags);
-       set_bit(ATM_VF_READY,&vcc->flags);
-       wake_up(&sigd_sleep);
-diff -urN linux-2.4.20/net/atm/svc.c linux-2.4.20-atm/net/atm/svc.c
---- linux-2.4.20/net/atm/svc.c Thu Apr 12 21:11:39 2001
-+++ linux-2.4.20-atm/net/atm/svc.c     Wed May 28 01:58:41 2003
-@@ -65,8 +65,8 @@
-       DPRINTK("svc_disconnect %p\n",vcc);
-       if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
--              sigd_enq(vcc,as_close,NULL,NULL,NULL);
-               add_wait_queue(&vcc->sleep,&wait);
-+              sigd_enq(vcc,as_close,NULL,NULL,NULL);
-               while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule();
-@@ -75,7 +75,7 @@
-       }
-       /* beware - socket is still in use by atmsigd until the last
-          as_indicate has been answered */
--      while ((skb = skb_dequeue(&vcc->listenq))) {
-+      while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
-               DPRINTK("LISTEN REL\n");
-               sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
-               dev_kfree_skb(skb);
-@@ -90,17 +90,19 @@
- static int svc_release(struct socket *sock)
- {
-       struct atm_vcc *vcc;
-+      struct sock *sk = sock->sk;
--      if (!sock->sk) return 0;
--      vcc = ATM_SD(sock);
--      DPRINTK("svc_release %p\n",vcc);
--      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
--             (thereby subjecting it to re-use) before all pending connections
--              are closed */
--      free_atm_vcc_sk(sock->sk);
-+      if (sk) {
-+              vcc = atm_sk(sk);
-+              DPRINTK("svc_release %p\n",vcc);
-+              sock_hold(sk);
-+              vcc_release(sock);
-+              svc_disconnect(vcc);
-+              /* VCC pointer is used as a reference, so we must not free it
-+                 (thereby subjecting it to re-use) before all pending
-+                 connections are closed */
-+              sock_put(sk);
-+      }
-       return 0;
- }
-@@ -125,8 +127,8 @@
-       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);
-       add_wait_queue(&vcc->sleep,&wait);
-+      sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local);
-       while (vcc->reply == WAITING && sigd) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule();
-@@ -169,13 +171,14 @@
-               if (!vcc->qos.txtp.traffic_class &&
-                   !vcc->qos.rxtp.traffic_class) return -EINVAL;
-               vcc->remote = *addr;
-+              add_wait_queue(&vcc->sleep,&wait);
-               vcc->reply = WAITING;
-               sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote);
-               if (flags & O_NONBLOCK) {
-+                      remove_wait_queue(&vcc->sleep,&wait);
-                       sock->state = SS_CONNECTING;
-                       return -EINPROGRESS;
-               }
--              add_wait_queue(&vcc->sleep,&wait);
-               error = 0;
-               while (vcc->reply == WAITING && sigd) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-@@ -228,7 +231,7 @@
- /*
-  * #endif
-  */
--      if (!(error = atm_connect(sock,vcc->itf,vcc->vpi,vcc->vci)))
-+      if (!(error = atm_connect(sock,vcc->sk->bound_dev_if,vcc->vpi,vcc->vci)))
-               sock->state = SS_CONNECTED;
-       else (void) svc_disconnect(vcc);
-       return error;
-@@ -243,9 +246,9 @@
-       DPRINTK("svc_listen %p\n",vcc);
-       /* let server handle listen on unbound sockets */
-       if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL;
-+      add_wait_queue(&vcc->sleep,&wait);
-       vcc->reply = WAITING;
-       sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
--      add_wait_queue(&vcc->sleep,&wait);
-       while (vcc->reply == WAITING && sigd) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule();
-@@ -253,7 +256,7 @@
-       remove_wait_queue(&vcc->sleep,&wait);
-       if (!sigd) return -EUNATCH;
-       set_bit(ATM_VF_LISTEN,&vcc->flags);
--      vcc->backlog_quota = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
-+      vcc->sk->max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
-       return vcc->reply;
- }
-@@ -277,7 +280,7 @@
-               DECLARE_WAITQUEUE(wait,current);
-               add_wait_queue(&old_vcc->sleep,&wait);
--              while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) {
-+              while (!(skb = skb_dequeue(&old_vcc->sk->receive_queue)) && sigd) {
-                       if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
-                       if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
-                               error = old_vcc->reply;
-@@ -306,16 +309,16 @@
-               error = atm_connect(newsock,msg->pvc.sap_addr.itf,
-                   msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
-               dev_kfree_skb(skb);
--              old_vcc->backlog_quota++;
-+              old_vcc->sk->ack_backlog--;
-               if (error) {
-                       sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
-                           &old_vcc->qos,error);
-                       return error == -EAGAIN ? -EBUSY : error;
-               }
-               /* wait should be short, so we ignore the non-blocking flag */
-+              add_wait_queue(&new_vcc->sleep,&wait);
-               new_vcc->reply = WAITING;
-               sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
--              add_wait_queue(&new_vcc->sleep,&wait);
-               while (new_vcc->reply == WAITING && sigd) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule();
-@@ -347,9 +350,9 @@
- {
-       DECLARE_WAITQUEUE(wait,current);
-+      add_wait_queue(&vcc->sleep,&wait);
-       vcc->reply = WAITING;
-       sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
--      add_wait_queue(&vcc->sleep,&wait);
-       while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags)
-           && sigd) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-@@ -390,37 +393,34 @@
- }
--static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = {
--      family:         PF_ATMSVC,
-+static struct proto_ops svc_proto_ops = {
-+      .family =       PF_ATMSVC,
--      release:        svc_release,
--      bind:           svc_bind,
--      connect:        svc_connect,
--      socketpair:     sock_no_socketpair,
--      accept:         svc_accept,
--      getname:        svc_getname,
--      poll:           atm_poll,
--      ioctl:          atm_ioctl,
--      listen:         svc_listen,
--      shutdown:       svc_shutdown,
--      setsockopt:     svc_setsockopt,
--      getsockopt:     svc_getsockopt,
--      sendmsg:        atm_sendmsg,
--      recvmsg:        atm_recvmsg,
--      mmap:           sock_no_mmap,
--      sendpage:       sock_no_sendpage,
-+      .release =      svc_release,
-+      .bind =         svc_bind,
-+      .connect =      svc_connect,
-+      .socketpair =   sock_no_socketpair,
-+      .accept =       svc_accept,
-+      .getname =      svc_getname,
-+      .poll =         atm_poll,
-+      .ioctl =        atm_ioctl,
-+      .listen =       svc_listen,
-+      .shutdown =     svc_shutdown,
-+      .setsockopt =   svc_setsockopt,
-+      .getsockopt =   svc_getsockopt,
-+      .sendmsg =      atm_sendmsg,
-+      .recvmsg =      atm_recvmsg,
-+      .mmap =         sock_no_mmap,
-+      .sendpage =     sock_no_sendpage,
- };
--#include <linux/smp_lock.h>
--SOCKOPS_WRAP(svc_proto, PF_ATMSVC);
--
- static int svc_create(struct socket *sock,int protocol)
- {
-       int error;
-       sock->ops = &svc_proto_ops;
--      error = atm_create(sock,protocol,AF_ATMSVC);
-+      error = vcc_create(sock,protocol,AF_ATMSVC);
-       if (error) return error;
-       ATM_SD(sock)->callback = svc_callback;
-       ATM_SD(sock)->local.sas_family = AF_ATMSVC;
-@@ -430,11 +430,8 @@
- static struct net_proto_family svc_family_ops = {
--      PF_ATMSVC,
--      svc_create,
--      0,                      /* no authentication */
--      0,                      /* no encryption */
--      0                       /* no encrypt_net */
-+      .family = PF_ATMSVC,
-+      .create = svc_create,
- };
-@@ -442,13 +439,19 @@
-  *    Initialize the ATM SVC protocol family
-  */
--static int __init atmsvc_init(void)
-+int __init atmsvc_init(void)
- {
--      if (sock_register(&svc_family_ops) < 0) {
--              printk(KERN_ERR "ATMSVC: can't register");
-+      int error;
-+
-+      error = sock_register(&svc_family_ops);
-+      if (error < 0) {
-+              printk(KERN_ERR "ATMSVC: can't register (%d)\n", error);
-               return -1;
-       }
-       return 0;
- }
--module_init(atmsvc_init);
-+void __exit atmsvc_exit(void)
-+{
-+      sock_unregister(PF_ATMSVC);
-+}
-diff -urN linux-2.4.20/net/ipv4/arp.c linux-2.4.20-atm/net/ipv4/arp.c
---- linux-2.4.20/net/ipv4/arp.c        Fri Nov 29 00:53:15 2002
-+++ linux-2.4.20-atm/net/ipv4/arp.c    Wed May 28 01:58:41 2003
-@@ -105,8 +105,9 @@
- #include <net/netrom.h>
- #endif
- #endif
--#ifdef CONFIG_ATM_CLIP
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
- #include <net/atmclip.h>
-+struct neigh_table *clip_tbl_hook = NULL;
- #endif
- #include <asm/system.h>
-@@ -438,8 +439,8 @@
-               if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
-                       nexthop = 0;
-               n = __neigh_lookup_errno(
--#ifdef CONFIG_ATM_CLIP
--                  dev->type == ARPHRD_ATM ? &clip_tbl :
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-+                  dev->type == ARPHRD_ATM ? clip_tbl_hook :
- #endif
-                   &arp_tbl, &nexthop, dev);
-               if (IS_ERR(n))
-diff -urN linux-2.4.20/net/netsyms.c linux-2.4.20-atm/net/netsyms.c
---- linux-2.4.20/net/netsyms.c Wed May 28 01:54:31 2003
-+++ linux-2.4.20-atm/net/netsyms.c     Wed May 28 01:58:41 2003
-@@ -45,6 +45,9 @@
- #include <linux/ip.h>
- #include <net/protocol.h>
- #include <net/arp.h>
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-+#include <net/atmclip.h>
-+#endif
- #include <net/ip.h>
- #include <net/udp.h>
- #include <net/tcp.h>
-@@ -160,6 +163,7 @@
- EXPORT_SYMBOL(put_cmsg);
- EXPORT_SYMBOL(sock_kmalloc);
- EXPORT_SYMBOL(sock_kfree_s);
-+EXPORT_SYMBOL(sockfd_lookup);
- #ifdef CONFIG_FILTER
- EXPORT_SYMBOL(sk_run_filter);
-@@ -461,6 +465,9 @@
- EXPORT_SYMBOL(ip_rcv);
- EXPORT_SYMBOL(arp_rcv);
- EXPORT_SYMBOL(arp_tbl);
-+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-+EXPORT_SYMBOL(clip_tbl_hook);
-+#endif
- EXPORT_SYMBOL(arp_find);
- #endif  /* CONFIG_INET */
-diff -urN linux-2.4.20/net/sched/Config.in linux-2.4.20-atm/net/sched/Config.in
---- linux-2.4.20/net/sched/Config.in   Fri Nov 29 00:53:16 2002
-+++ linux-2.4.20-atm/net/sched/Config.in       Wed May 28 01:58:41 2003
-@@ -6,8 +6,8 @@
- tristate '  CSZ packet scheduler' CONFIG_NET_SCH_CSZ
- #tristate '  H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
- #tristate '  H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
--if [ "$CONFIG_ATM" = "y" ]; then
--   bool '  ATM pseudo-scheduler' CONFIG_NET_SCH_ATM
-+if [ "$CONFIG_ATM" != "n" ]; then
-+   dep_tristate '  ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM
- fi
- tristate '  The simplest PRIO pseudoscheduler' CONFIG_NET_SCH_PRIO
- tristate '  RED queue' CONFIG_NET_SCH_RED
-diff -urN linux-2.4.20/net/sched/sch_atm.c linux-2.4.20-atm/net/sched/sch_atm.c
---- linux-2.4.20/net/sched/sch_atm.c   Wed May 28 01:54:31 2003
-+++ linux-2.4.20-atm/net/sched/sch_atm.c       Wed May 28 01:59:30 2003
-@@ -512,7 +512,6 @@
-                       memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
-                           flow->hdr_len);
-                       atomic_add(skb->truesize,&flow->vcc->sk->wmem_alloc);
--                      ATM_SKB(skb)->iovcnt = 0;
-                       /* atm.atm_options are already set by atm_tc_enqueue */
-                       (void) flow->vcc->send(flow->vcc,skb);
-               }
This page took 0.445092 seconds and 4 git commands to generate.