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

diff -urN linux-2.4.21-bk10/Makefile linux-2.4.21-bk11/Makefile
--- linux-2.4.21-bk10/Makefile	2003-07-16 02:53:46.000000000 -0700
+++ linux-2.4.21-bk11/Makefile	2003-07-16 02:53:53.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 21
-EXTRAVERSION = -bk10
+EXTRAVERSION = -bk11
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.21-bk10/arch/alpha/config.in linux-2.4.21-bk11/arch/alpha/config.in
--- linux-2.4.21-bk10/arch/alpha/config.in	2003-07-16 02:53:46.000000000 -0700
+++ linux-2.4.21-bk11/arch/alpha/config.in	2003-07-16 02:53:53.000000000 -0700
@@ -367,7 +367,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.21-bk10/arch/cris/config.in linux-2.4.21-bk11/arch/cris/config.in
--- linux-2.4.21-bk10/arch/cris/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/cris/config.in	2003-07-16 02:53:53.000000000 -0700
@@ -210,7 +210,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.21-bk10/arch/i386/config.in linux-2.4.21-bk11/arch/i386/config.in
--- linux-2.4.21-bk10/arch/i386/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/i386/config.in	2003-07-16 02:53:53.000000000 -0700
@@ -393,7 +393,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.21-bk10/arch/ia64/config.in linux-2.4.21-bk11/arch/ia64/config.in
--- linux-2.4.21-bk10/arch/ia64/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/ia64/config.in	2003-07-16 02:53:53.000000000 -0700
@@ -179,7 +179,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.21-bk10/arch/parisc/config.in linux-2.4.21-bk11/arch/parisc/config.in
--- linux-2.4.21-bk10/arch/parisc/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/parisc/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -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.21-bk10/arch/ppc/config.in linux-2.4.21-bk11/arch/ppc/config.in
--- linux-2.4.21-bk10/arch/ppc/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/ppc/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -324,7 +324,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.21-bk10/arch/ppc64/config.in linux-2.4.21-bk11/arch/ppc64/config.in
--- linux-2.4.21-bk10/arch/ppc64/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/ppc64/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -141,7 +141,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.21-bk10/arch/sh/config.in linux-2.4.21-bk11/arch/sh/config.in
--- linux-2.4.21-bk10/arch/sh/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/sh/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -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.21-bk10/arch/sparc/config.in linux-2.4.21-bk11/arch/sparc/config.in
--- linux-2.4.21-bk10/arch/sparc/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/sparc/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -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.21-bk10/arch/sparc64/config.in linux-2.4.21-bk11/arch/sparc64/config.in
--- linux-2.4.21-bk10/arch/sparc64/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/sparc64/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -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.21-bk10/arch/x86_64/config.in linux-2.4.21-bk11/arch/x86_64/config.in
--- linux-2.4.21-bk10/arch/x86_64/config.in	2003-07-16 02:53:47.000000000 -0700
+++ linux-2.4.21-bk11/arch/x86_64/config.in	2003-07-16 02:53:54.000000000 -0700
@@ -168,7 +168,7 @@
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
       source drivers/net/Config.in
 # seems to be largely not 64bit safe	   
-#      if [ "$CONFIG_ATM" = "y" ]; then
+#      if [ "$CONFIG_ATM" != "n" ]; then
 #         source drivers/atm/Config.in
 #      fi
    fi
diff -urN linux-2.4.21-bk10/drivers/atm/Config.in linux-2.4.21-bk11/drivers/atm/Config.in
--- linux-2.4.21-bk10/drivers/atm/Config.in	2003-07-16 02:53:48.000000000 -0700
+++ linux-2.4.21-bk11/drivers/atm/Config.in	2003-07-16 02:53:55.000000000 -0700
@@ -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
@@ -93,7 +93,7 @@
   fi
 fi
 if [ "$CONFIG_PCI" = "y" ]; then
-  tristate 'ForeRunner HE Series' CONFIG_ATM_HE
+  dep_tristate 'ForeRunner HE Series' CONFIG_ATM_HE $CONFIG_ATM
   if [ "$CONFIG_ATM_HE" != "n" ]; then
     bool 'Use S/UNI PHY driver' CONFIG_ATM_HE_USE_SUNI
   fi
diff -urN linux-2.4.21-bk10/drivers/atm/atmtcp.c linux-2.4.21-bk11/drivers/atm/atmtcp.c
--- linux-2.4.21-bk10/drivers/atm/atmtcp.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.21-bk11/drivers/atm/atmtcp.c	2003-07-16 02:53:55.000000000 -0700
@@ -153,6 +153,7 @@
 
 static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
 {
+	unsigned long flags;
 	struct atm_cirange ci;
 	struct atm_vcc *vcc;
 
@@ -162,9 +163,14 @@
 	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;
+	spin_lock_irqsave(&dev->lock, flags);
 	for (vcc = dev->vccs; vcc; vcc = vcc->next)
 		if ((vcc->vpi >> ci.vpi_bits) ||
-		    (vcc->vci >> ci.vci_bits)) return -EBUSY;
+		    (vcc->vci >> ci.vci_bits)) {
+			spin_unlock_irqrestore(&dev->lock, flags);
+			return -EBUSY;
+		}
+	spin_unlock_irqrestore(&dev->lock, flags);
 	dev->ci_range = ci;
 	return 0;
 }
@@ -227,6 +233,7 @@
 
 static void atmtcp_c_close(struct atm_vcc *vcc)
 {
+	unsigned long flags;
 	struct atm_dev *atmtcp_dev;
 	struct atmtcp_dev_data *dev_data;
 	struct atm_vcc *walk;
@@ -239,13 +246,16 @@
 	kfree(dev_data);
 	shutdown_atm_dev(atmtcp_dev);
 	vcc->dev_data = NULL;
+	spin_lock_irqsave(&atmtcp_dev->lock, flags);
 	for (walk = atmtcp_dev->vccs; walk; walk = walk->next)
 		wake_up(&walk->sleep);
+	spin_unlock_irqrestore(&atmtcp_dev->lock, flags);
 }
 
 
 static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
 {
+	unsigned long flags;
 	struct atm_dev *dev;
 	struct atmtcp_hdr *hdr;
 	struct atm_vcc *out_vcc;
@@ -260,11 +270,13 @@
 		    (struct atmtcp_control *) skb->data);
 		goto done;
 	}
+	spin_lock_irqsave(&dev->lock, flags);
 	for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next)
 		if (out_vcc->vpi == ntohs(hdr->vpi) &&
 		    out_vcc->vci == ntohs(hdr->vci) &&
 		    out_vcc->qos.rxtp.traffic_class != ATM_NONE)
 			break;
+	spin_unlock_irqrestore(&dev->lock, flags);
 	if (!out_vcc) {
 		atomic_inc(&vcc->stats->tx_err);
 		goto done;
@@ -293,13 +305,13 @@
 
 
 static struct atmdev_ops atmtcp_v_dev_ops = {
-	dev_close:	atmtcp_v_dev_close,
-	open:		atmtcp_v_open,
-	close:		atmtcp_v_close,
-	ioctl:		atmtcp_v_ioctl,
-	send:		atmtcp_v_send,
-	proc_read:	atmtcp_v_proc,
-	owner:		THIS_MODULE
+	.dev_close	= atmtcp_v_dev_close,
+	.open		= atmtcp_v_open,
+	.close		= atmtcp_v_close,
+	.ioctl		= atmtcp_v_ioctl,
+	.send		= atmtcp_v_send,
+	.proc_read	= atmtcp_v_proc,
+	.owner		= THIS_MODULE
 };
 
 
@@ -309,21 +321,16 @@
 
 
 static struct atmdev_ops atmtcp_c_dev_ops = {
-	close:		atmtcp_c_close,
-	send:		atmtcp_c_send
+	.close		= atmtcp_c_close,
+	.send		= atmtcp_c_send
 };
 
 
 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 +363,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 {
@@ -389,14 +399,18 @@
 	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;
 }
diff -urN linux-2.4.21-bk10/drivers/atm/eni.c linux-2.4.21-bk11/drivers/atm/eni.c
--- linux-2.4.21-bk10/drivers/atm/eni.c	2003-07-16 02:53:48.000000000 -0700
+++ linux-2.4.21-bk11/drivers/atm/eni.c	2003-07-16 02:53:55.000000000 -0700
@@ -1887,8 +1887,10 @@
 
 static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci)
 {
+	unsigned long flags;
 	struct atm_vcc *walk;
 
+	spin_lock_irqsave(&vcc->dev->lock, flags);
 	if (*vpi == ATM_VPI_ANY) *vpi = 0;
 	if (*vci == ATM_VCI_ANY) {
 		for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) {
@@ -1907,17 +1909,29 @@
 			}
 			break;
 		}
+		spin_unlock_irqrestore(&vcc->dev->lock, flags);
 		return *vci == NR_VCI ? -EADDRINUSE : 0;
 	}
-	if (*vci == ATM_VCI_UNSPEC) return 0;
+	if (*vci == ATM_VCI_UNSPEC) {
+		spin_unlock_irqrestore(&vcc->dev->lock, flags);
+		return 0;
+	}
 	if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
-	    ENI_DEV(vcc->dev)->rx_map[*vci])
+	    ENI_DEV(vcc->dev)->rx_map[*vci]) {
+		spin_unlock_irqrestore(&vcc->dev->lock, flags);
 		return -EADDRINUSE;
-	if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
+	}
+	if (vcc->qos.txtp.traffic_class == ATM_NONE) {
+		spin_unlock_irqrestore(&vcc->dev->lock, flags);
+		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)
+		    walk->qos.txtp.traffic_class != ATM_NONE) {
+			spin_unlock_irqrestore(&vcc->dev->lock, flags);
 			return -EADDRINUSE;
+		}
+	spin_unlock_irqrestore(&vcc->dev->lock, flags);
 	return 0;
 }
 
@@ -2125,6 +2139,7 @@
 
 static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
 {
+	unsigned long flags;
 	static const char *signal[] = { "LOST","unknown","okay" };
 	struct eni_dev *eni_dev = ENI_DEV(dev);
 	struct atm_vcc *vcc;
@@ -2197,6 +2212,7 @@
 		return sprintf(page,"%10sbacklog %u packets\n","",
 		    skb_queue_len(&tx->backlog));
 	}
+	spin_lock_irqsave(&dev->lock, flags);
 	for (vcc = dev->vccs; vcc; vcc = vcc->next) {
 		struct eni_vcc *eni_vcc = ENI_VCC(vcc);
 		int length;
@@ -2215,8 +2231,10 @@
 			length += sprintf(page+length,"tx[%d], txing %d bytes",
 			    eni_vcc->tx->index,eni_vcc->txing);
 		page[length] = '\n';
+		spin_unlock_irqrestore(&dev->lock, flags);
 		return length+1;
 	}
+	spin_unlock_irqrestore(&dev->lock, flags);
 	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.21-bk10/drivers/atm/fore200e.c linux-2.4.21-bk11/drivers/atm/fore200e.c
--- linux-2.4.21-bk10/drivers/atm/fore200e.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.21-bk11/drivers/atm/fore200e.c	2003-07-16 02:53:55.000000000 -0700
@@ -1077,13 +1077,16 @@
 static struct atm_vcc* 
 fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
 {
+    unsigned long flags;
     struct atm_vcc* vcc;
 
+    spin_lock_irqsave(&fore200e->atm_dev->lock, flags);
     for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
 
 	if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci)
 	    break;
     }
+    spin_unlock_irqrestore(&fore200e->atm_dev->lock, flags);
     
     return vcc;
 }
@@ -1354,9 +1357,13 @@
 static int
 fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci)
 {
+    unsigned long flags;
     struct atm_vcc* walk;
 
     /* find a free VPI */
+
+    spin_lock_irqsave(&vcc->dev->lock, flags);
+
     if (*vpi == ATM_VPI_ANY) {
 
 	for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) {
@@ -1380,6 +1387,8 @@
 	}
     }
 
+    spin_unlock_irqrestore(&vcc->dev->lock, flags);
+
     return 0;
 }
 
@@ -2640,6 +2649,7 @@
 static int
 fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
 {
+    unsigned long flags;
     struct fore200e* fore200e  = FORE200E_DEV(dev);
     int              len, left = *pos;
 
@@ -2886,6 +2896,7 @@
 	len = sprintf(page,"\n"    
 		      " VCCs:\n  address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n");
 	
+	spin_lock_irqsave(&fore200e->atm_dev->lock, flags);
 	for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
 
 	    fore200e_vcc = FORE200E_VCC(vcc);
@@ -2900,6 +2911,7 @@
 			   fore200e_vcc->rx_max_pdu
 		);
 	}
+	spin_unlock_irqrestore(&fore200e->atm_dev->lock, flags);
 
 	return len;
     }
diff -urN linux-2.4.21-bk10/drivers/atm/he.c linux-2.4.21-bk11/drivers/atm/he.c
--- linux-2.4.21-bk10/drivers/atm/he.c	2003-07-16 02:53:48.000000000 -0700
+++ linux-2.4.21-bk11/drivers/atm/he.c	2003-07-16 02:53:55.000000000 -0700
@@ -329,6 +329,7 @@
 static __inline__ struct atm_vcc*
 he_find_vcc(struct he_dev *he_dev, unsigned cid)
 {
+	unsigned long flags;
 	struct atm_vcc *vcc;
 	short vpi;
 	int vci;
@@ -336,10 +337,15 @@
 	vpi = cid >> he_dev->vcibits;
 	vci = cid & ((1 << he_dev->vcibits) - 1);
 
+	spin_lock_irqsave(&he_dev->atm_dev->lock, flags);
 	for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next)
 		if (vcc->vci == vci && vcc->vpi == vpi
-			&& vcc->qos.rxtp.traffic_class != ATM_NONE) return vcc;
+			&& vcc->qos.rxtp.traffic_class != ATM_NONE) {
+				spin_unlock_irqrestore(&he_dev->atm_dev->lock, flags);
+				return vcc;
+			}
 
+	spin_unlock_irqrestore(&he_dev->atm_dev->lock, flags);
 	return NULL;
 }
 
diff -urN linux-2.4.21-bk10/drivers/atm/idt77252.c linux-2.4.21-bk11/drivers/atm/idt77252.c
--- linux-2.4.21-bk10/drivers/atm/idt77252.c	2003-07-16 02:53:48.000000000 -0700
+++ linux-2.4.21-bk11/drivers/atm/idt77252.c	2003-07-16 02:53:55.000000000 -0700
@@ -2404,8 +2404,10 @@
 static int
 idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci)
 {
+	unsigned long flags;
 	struct atm_vcc *walk;
 
+	spin_lock_irqsave(&vcc->dev->lock, flags);
 	if (*vpi == ATM_VPI_ANY) {
 		*vpi = 0;
 		walk = vcc->dev->vccs;
@@ -2432,6 +2434,7 @@
 		}
 	}
 
+	spin_unlock_irqrestore(&vcc->dev->lock, flags);
 	return 0;
 }
 
diff -urN linux-2.4.21-bk10/drivers/net/Config.in linux-2.4.21-bk11/drivers/net/Config.in
--- linux-2.4.21-bk10/drivers/net/Config.in	2003-07-16 02:53:48.000000000 -0700
+++ linux-2.4.21-bk11/drivers/net/Config.in	2003-07-16 02:53:55.000000000 -0700
@@ -312,7 +312,7 @@
       dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
    fi
    if [ ! "$CONFIG_ATM" = "n" ]; then
-      dep_tristate '  PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP $CONFIG_EXPERIMENTAL
+      dep_tristate '  PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP $CONFIG_EXPERIMENTAL $CONFIG_ATM
    fi
 fi
 
diff -urN linux-2.4.21-bk10/drivers/net/sunhme.c linux-2.4.21-bk11/drivers/net/sunhme.c
--- linux-2.4.21-bk10/drivers/net/sunhme.c	2003-07-16 02:53:49.000000000 -0700
+++ linux-2.4.21-bk11/drivers/net/sunhme.c	2003-07-16 02:53:55.000000000 -0700
@@ -2798,8 +2798,8 @@
 	dev->watchdog_timeo = 5*HZ;
 	dev->do_ioctl = &happy_meal_ioctl;
 
-	/* Happy Meal can do it all... */
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	/* Happy Meal can do it all... except VLAN. */
+	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
 
 	dev->irq = sdev->irqs[0];
 
diff -urN linux-2.4.21-bk10/include/linux/atmdev.h linux-2.4.21-bk11/include/linux/atmdev.h
--- linux-2.4.21-bk10/include/linux/atmdev.h	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/include/linux/atmdev.h	2003-07-16 02:53:56.000000000 -0700
@@ -341,6 +341,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 */
@@ -402,7 +404,7 @@
 
 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);
+struct atm_dev *atm_dev_lookup(int number);
 void atm_dev_deregister(struct atm_dev *dev);
 void shutdown_atm_dev(struct atm_dev *dev);
 void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev);
@@ -413,30 +415,46 @@
  *
  */
 
-static __inline__ int atm_guess_pdu2truesize(int pdu_size)
+static inline int atm_guess_pdu2truesize(int pdu_size)
 {
 	return ((pdu_size+15) & ~15) + sizeof(struct sk_buff);
 }
 
 
-static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize)
+static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
 {
 	atomic_add(truesize, &vcc->sk->rmem_alloc);
 }
 
 
-static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
+static inline void atm_return(struct atm_vcc *vcc,int truesize)
 {
 	atomic_sub(truesize, &vcc->sk->rmem_alloc);
 }
 
 
-static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
+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 void atm_dev_hold(struct atm_dev *dev)
+{
+	atomic_inc(&dev->refcnt);
+}
+
+
+static inline 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);
+}
+
+
 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);
diff -urN linux-2.4.21-bk10/include/linux/net.h linux-2.4.21-bk11/include/linux/net.h
--- linux-2.4.21-bk10/include/linux/net.h	2001-11-22 11:46:19.000000000 -0800
+++ linux-2.4.21-bk11/include/linux/net.h	2003-07-16 02:53:56.000000000 -0700
@@ -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.21-bk10/net/Config.in linux-2.4.21-bk11/net/Config.in
--- linux-2.4.21-bk10/net/Config.in	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/Config.in	2003-07-16 02:53:56.000000000 -0700
@@ -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
-	 tristate '  Classical IP over ATM' CONFIG_ATM_CLIP
+	 dep_tristate '  Classical IP over ATM' CONFIG_ATM_CLIP $CONFIG_ATM
 	 if [ "$CONFIG_ATM_CLIP" != "n" ]; 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
       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.21-bk10/net/atm/Makefile linux-2.4.21-bk11/net/atm/Makefile
--- linux-2.4.21-bk10/net/atm/Makefile	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/Makefile	2003-07-16 02:53:56.000000000 -0700
@@ -14,7 +14,10 @@
 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
+ifeq ($(CONFIG_ATM),m)
+  obj-m += $(O_TARGET)
+endif
 
 ifneq ($(CONFIG_ATM_CLIP),n)
   NEED_IPCOM = ipcommon.o
@@ -31,13 +34,13 @@
 obj-$(CONFIG_ATM_BR2684) += br2684.o
 
 ifeq ($(CONFIG_NET_SCH_ATM),y)
-NEED_IPCOM = ipcommon.o
+  NEED_IPCOM = ipcommon.o
 endif
 
 obj-y += $(NEED_IPCOM)
 
 ifeq ($(CONFIG_PROC_FS),y)
-obj-y += proc.o
+  obj-y += proc.o
 endif
 
 obj-$(CONFIG_ATM_LANE) += lec.o
diff -urN linux-2.4.21-bk10/net/atm/addr.c linux-2.4.21-bk11/net/atm/addr.c
--- linux-2.4.21-bk10/net/atm/addr.c	2001-04-06 10:51:19.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/addr.c	2003-07-16 02:53:56.000000000 -0700
@@ -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;
@@ -52,46 +44,46 @@
 	sigd_enq(NULL,as_itf_notify,NULL,&pvc,NULL);
 }
 
-/*
- *	This is called from atm_ioctl only. You must hold the lock as a caller
- */
 
 void atm_reset_addr(struct atm_dev *dev)
 {
+	unsigned long flags;
 	struct atm_dev_addr *this;
 
-	down(&local_lock);
+	spin_lock_irqsave(&dev->lock, flags);
 	while (dev->local) {
 		this = dev->local;
 		dev->local = this->next;
 		kfree(this);
 	}
-	up(&local_lock);
+	spin_unlock_irqrestore(&dev->lock, flags);
 	notify_sigd(dev);
 }
 
 
 int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
 {
+	unsigned long flags;
 	struct atm_dev_addr **walk;
 	int error;
 
 	error = check_addr(addr);
-	if (error) return error;
-	down(&local_lock);
+	if (error)
+		return error;
+	spin_lock_irqsave(&dev->lock, flags);
 	for (walk = &dev->local; *walk; walk = &(*walk)->next)
 		if (identical(&(*walk)->addr,addr)) {
-			up(&local_lock);
+			spin_unlock_irqrestore(&dev->lock, flags);
 			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_irqrestore(&dev->lock, flags);
 		return -ENOMEM;
 	}
 	(*walk)->addr = *addr;
 	(*walk)->next = NULL;
-	up(&local_lock);
+	spin_unlock_irqrestore(&dev->lock, flags);
 	notify_sigd(dev);
 	return 0;
 }
@@ -99,22 +91,24 @@
 
 int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
 {
+	unsigned long flags;
 	struct atm_dev_addr **walk,*this;
 	int error;
 
 	error = check_addr(addr);
-	if (error) return error;
-	down(&local_lock);
+	if (error)
+		return error;
+	spin_lock_irqsave(&dev->lock, flags);
 	for (walk = &dev->local; *walk; walk = &(*walk)->next)
 		if (identical(&(*walk)->addr,addr)) break;
 	if (!*walk) {
-		up(&local_lock);
+		spin_unlock_irqrestore(&dev->lock, flags);
 		return -ENOENT;
 	}
 	this = *walk;
 	*walk = this->next;
 	kfree(this);
-	up(&local_lock);
+	spin_unlock_irqrestore(&dev->lock, flags);
 	notify_sigd(dev);
 	return 0;
 }
@@ -122,24 +116,25 @@
 
 int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size)
 {
+	unsigned long flags;
 	struct atm_dev_addr *walk;
 	int total;
 
-	down(&local_lock);
+	spin_lock_irqsave(&dev->lock, flags);
 	total = 0;
 	for (walk = dev->local; walk; walk = walk->next) {
 		total += sizeof(struct sockaddr_atmsvc);
 		if (total > size) {
-			up(&local_lock);
+			spin_unlock_irqrestore(&dev->lock, flags);
 			return -E2BIG;
 		}
 		if (copy_to_user(u_buf,&walk->addr,
 		    sizeof(struct sockaddr_atmsvc))) {
-			up(&local_lock);
+			spin_unlock_irqrestore(&dev->lock, flags);
 			return -EFAULT;
 		}
 		u_buf++;
 	}
-	up(&local_lock);
+	spin_unlock_irqrestore(&dev->lock, flags);
 	return total;
 }
diff -urN linux-2.4.21-bk10/net/atm/atm_misc.c linux-2.4.21-bk11/net/atm/atm_misc.c
--- linux-2.4.21-bk10/net/atm/atm_misc.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/atm_misc.c	2003-07-16 02:53:56.000000000 -0700
@@ -63,13 +63,19 @@
 
 int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
 {
+	unsigned long flags;
 	static short p = 0; /* poor man's per-device cache */
 	static int c = 0;
 	short old_p;
 	int old_c;
+	int err;
 
-	if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY)
-		return check_ci(vcc,*vpi,*vci);
+	spin_lock_irqsave(&vcc->dev->lock, flags);
+	if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY) {
+		err = check_ci(vcc,*vpi,*vci);
+		spin_unlock_irqrestore(&vcc->dev->lock, flags);
+		return err;
+	}
 	/* 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;
@@ -82,6 +88,7 @@
 		if (!check_ci(vcc,p,c)) {
 			*vpi = p;
 			*vci = c;
+			spin_unlock_irqrestore(&vcc->dev->lock, flags);
 			return 0;
 		}
 		if (*vci == ATM_VCI_ANY) {
@@ -96,6 +103,7 @@
 		}
 	}
 	while (old_p != p || old_c != c);
+	spin_unlock_irqrestore(&vcc->dev->lock, flags);
 	return -EADDRINUSE;
 }
 
diff -urN linux-2.4.21-bk10/net/atm/clip.c linux-2.4.21-bk11/net/atm/clip.c
--- linux-2.4.21-bk10/net/atm/clip.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/clip.c	2003-07-16 02:53:56.000000000 -0700
@@ -713,9 +713,10 @@
 
 
 static struct atm_dev atmarpd_dev = {
-	.ops =			&atmarpd_dev_ops,
-	.type =			"arpd",
-	.number =		999,
+	.ops =		&atmarpd_dev_ops,
+	.type =		"arpd",
+	.number =	999,
+	.lock =		SPIN_LOCK_UNLOCKED
 };
 
 
diff -urN linux-2.4.21-bk10/net/atm/common.c linux-2.4.21-bk11/net/atm/common.c
--- linux-2.4.21-bk10/net/atm/common.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/common.c	2003-07-16 02:53:56.000000000 -0700
@@ -21,6 +21,7 @@
 #include <linux/time.h>		/* struct timeval */
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
+#include <linux/init.h>
 #include <net/sock.h>		/* struct sock */
 
 #include <asm/uaccess.h>
@@ -116,7 +117,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)
 {
@@ -178,19 +178,18 @@
 			atm_return(vcc,skb->truesize);
 			kfree_skb(skb);
 		}
-		spin_lock (&atm_dev_lock);	
-		fops_put (vcc->dev->ops);
+
+		if (vcc->dev->ops->owner)
+			__MOD_DEC_USE_COUNT(vcc->dev->ops->owner);
+		atm_dev_release(vcc->dev);
 		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);
-
-	spin_unlock (&atm_dev_lock);
 }
 
 
@@ -283,11 +282,13 @@
 	    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 (!try_inc_mod_count(dev->ops->owner))
+		return -ENODEV;
 	if (dev->ops->open) {
 		error = dev->ops->open(vcc,vpi,vci);
 		if (error) {
-			fops_put (dev->ops);
+			if (dev->ops->owner)
+				__MOD_DEC_USE_COUNT(dev->ops->owner);
 			bind_vcc(vcc,NULL);
 			return error;
 		}
@@ -301,14 +302,13 @@
 	struct atm_dev *dev;
 	int return_val;
 
-	spin_lock (&atm_dev_lock);
-	dev = atm_find_dev(itf);
+	dev = atm_dev_lookup(itf);
 	if (!dev)
 		return_val =  -ENODEV;
-	else
+	else {
 		return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
-
-	spin_unlock (&atm_dev_lock);
+		if (return_val) atm_dev_release(dev);
+	}
 
 	return return_val;
 }
@@ -339,15 +339,20 @@
 	}
 	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) {
+		spin_lock(&atm_dev_lock);
+		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;
+			atm_dev_hold(dev);
+			spin_unlock(&atm_dev_lock);
+			if (!atm_do_connect_dev(vcc,dev,vpi,vci))
+				break;
+			atm_dev_release(dev);
 			dev = NULL;
+			spin_lock(&atm_dev_lock);
 		}
-		spin_unlock (&atm_dev_lock);
+		spin_unlock(&atm_dev_lock);
 		if (!dev) return -ENODEV;
 	}
 	if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
@@ -565,7 +570,6 @@
 	int error,len,size,number, ret_val;
 
 	ret_val = 0;
-	spin_lock (&atm_dev_lock);
 	vcc = ATM_SD(sock);
 	switch (cmd) {
 		case SIOCOUTQ:
@@ -603,14 +607,17 @@
 				goto done;
 			}
 			size = 0;
+			spin_lock(&atm_dev_lock);
 			list_for_each(p, &atm_devs)
 				size += sizeof(int);
 			if (size > len) {
+				spin_unlock(&atm_dev_lock);
 				ret_val = -E2BIG;
 				goto done;
 			}
-			tmp_buf = kmalloc(size,GFP_KERNEL);
+			tmp_buf = kmalloc(size, GFP_ATOMIC);
 			if (!tmp_buf) {
+				spin_unlock(&atm_dev_lock);
 				ret_val = -ENOMEM;
 				goto done;
 			}
@@ -619,6 +626,7 @@
 				dev = list_entry(p, struct atm_dev, dev_list);
 				*tmp_p++ = dev->number;
 			}
+			spin_unlock(&atm_dev_lock);
 		        ret_val = ((copy_to_user(buf, tmp_buf, size)) ||
 			    put_user(size, &((struct atm_iobuf *) arg)->length)
 			    ) ? -EFAULT : 0;
@@ -845,7 +853,7 @@
 		ret_val = -EFAULT;
 		goto done;
 	}
-	if (!(dev = atm_find_dev(number))) {
+	if (!(dev = atm_dev_lookup(number))) {
 		ret_val = -ENODEV;
 		goto done;
 	}
@@ -856,14 +864,14 @@
 			size = strlen(dev->type)+1;
 			if (copy_to_user(buf,dev->type,size)) {
 				ret_val = -EFAULT;
-				goto done;
+				goto done_release;
 			}
 			break;
 		case ATM_GETESI:
 			size = ESI_LEN;
 			if (copy_to_user(buf,dev->esi,size)) {
 				ret_val = -EFAULT;
-				goto done;
+				goto done_release;
 			}
 			break;
 		case ATM_SETESI:
@@ -873,7 +881,7 @@
 				for (i = 0; i < ESI_LEN; i++)
 					if (dev->esi[i]) {
 						ret_val = -EEXIST;
-						goto done;
+						goto done_release;
 					}
 			}
 			/* fall through */
@@ -883,20 +891,20 @@
 
 				if (!capable(CAP_NET_ADMIN)) {
 					ret_val = -EPERM;
-					goto done;
+					goto done_release;
 				}
 				if (copy_from_user(esi,buf,ESI_LEN)) {
 					ret_val = -EFAULT;
-					goto done;
+					goto done_release;
 				}
 				memcpy(dev->esi,esi,ESI_LEN);
 				ret_val =  ESI_LEN;
-				goto done;
+				goto done_release;
 			}
 		case ATM_GETSTATZ:
 			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-				goto done;
+				goto done_release;
 			}
 			/* fall through */
 		case ATM_GETSTAT:
@@ -904,27 +912,27 @@
 			error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ);
 			if (error) {
 				ret_val = error;
-				goto done;
+				goto done_release;
 			}
 			break;
 		case ATM_GETCIRANGE:
 			size = sizeof(struct atm_cirange);
 			if (copy_to_user(buf,&dev->ci_range,size)) {
 				ret_val = -EFAULT;
-				goto done;
+				goto done_release;
 			}
 			break;
 		case ATM_GETLINKRATE:
 			size = sizeof(int);
 			if (copy_to_user(buf,&dev->link_rate,size)) {
 				ret_val = -EFAULT;
-				goto done;
+				goto done_release;
 			}
 			break;
 		case ATM_RSTADDR:
 			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-				goto done;
+				goto done_release;
 			}
 			atm_reset_addr(dev);
 			break;
@@ -932,20 +940,20 @@
 		case ATM_DELADDR:
 			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-				goto done;
+				goto done_release;
 			}
 			{
 				struct sockaddr_atmsvc addr;
 
 				if (copy_from_user(&addr,buf,sizeof(addr))) {
 					ret_val = -EFAULT;
-					goto done;
+					goto done_release;
 				}
 				if (cmd == ATM_ADDADDR)
 					ret_val = atm_add_addr(dev,&addr);
 				else
 					ret_val = atm_del_addr(dev,&addr);
-				goto done;
+				goto done_release;
 			}
 		case ATM_GETADDR:
 			size = atm_get_addr(dev,buf,len);
@@ -956,13 +964,13 @@
 			   write the length" */
 				ret_val = put_user(size,
 						   &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
-			goto done;
+			goto done_release;
 		case ATM_SETLOOP:
 			if (__ATM_LM_XTRMT((int) (long) buf) &&
 			    __ATM_LM_XTLOC((int) (long) buf) >
 			    __ATM_LM_XTRMT((int) (long) buf)) {
 				ret_val = -EINVAL;
-				goto done;
+				goto done_release;
 			}
 			/* fall through */
 		case ATM_SETCIRANGE:
@@ -972,18 +980,18 @@
 		case SONET_SETFRAMING:
 			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-				goto done;
+				goto done_release;
 			}
 			/* fall through */
 		default:
 			if (!dev->ops->ioctl) {
 				ret_val = -EINVAL;
-				goto done;
+				goto done_release;
 			}
 			size = dev->ops->ioctl(dev,cmd,buf);
 			if (size < 0) {
 				ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size);
-				goto done;
+				goto done_release;
 			}
 	}
 	
@@ -992,9 +1000,10 @@
 			-EFAULT : 0;
 	else
 		ret_val = 0;
+done_release:
+	atm_dev_release(dev);
 
- done:
-	spin_unlock (&atm_dev_lock); 
+done:
 	return ret_val;
 }
 
@@ -1209,3 +1218,43 @@
         return;
 }        
 #endif
+
+static int __init atm_init(void)
+{
+	int error;
+
+	if ((error = atmpvc_init()) < 0) {
+		printk(KERN_ERR "atmpvc_init() failed with %d\n", error);
+		goto failure;
+	}
+	if ((error = atmsvc_init()) < 0) {
+		printk(KERN_ERR "atmsvc_init() failed with %d\n", error);
+		goto failure;
+	}
+#ifdef CONFIG_PROC_FS
+        if ((error = atm_proc_init()) < 0) {
+		printk(KERN_ERR "atm_proc_init() failed with %d\n",error);
+		goto failure;
+	}
+#endif
+	return 0;
+
+failure:
+	atmsvc_exit();
+	atmpvc_exit();
+	return error;
+}
+
+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.21-bk10/net/atm/common.h linux-2.4.21-bk11/net/atm/common.h
--- linux-2.4.21-bk10/net/atm/common.h	2000-12-11 13:33:43.000000000 -0800
+++ linux-2.4.21-bk11/net/atm/common.h	2003-07-16 02:53:56.000000000 -0700
@@ -28,7 +28,12 @@
 void atm_release_vcc_sk(struct sock *sk,int free_sk);
 void atm_shutdown_dev(struct atm_dev *dev);
 
+int atmpvc_init(void);
+void atmpvc_exit(void);
+int atmsvc_init(void);
+void atmsvc_exit(void);
 int atm_proc_init(void);
+void atm_proc_exit(void);
 
 /* SVC */
 
diff -urN linux-2.4.21-bk10/net/atm/lec.c linux-2.4.21-bk11/net/atm/lec.c
--- linux-2.4.21-bk10/net/atm/lec.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/lec.c	2003-07-16 02:53:56.000000000 -0700
@@ -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
@@ -51,10 +52,12 @@
 #define DPRINTK(format,args...)
 #endif
 
+struct net_bridge;
 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
@@ -550,20 +553,15 @@
 }
 
 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
 };
 
 /*
@@ -1054,15 +1052,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);
 }
 
 /*
@@ -1113,33 +1111,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]);
 }
 
 /*
@@ -1149,16 +1147,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]);
@@ -1170,7 +1167,7 @@
                         tmp = tmp->next;
                 }
                 if (!tmp) {/* Entry was not found */
-                        restore_flags(flags);
+                        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
                         return -1;
                 }
         }
@@ -1196,7 +1193,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],
@@ -1381,12 +1380,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);
         
         /*
@@ -1429,7 +1424,6 @@
         priv->mcast_vcc = NULL;
         memset(priv->lec_arp_tables, 0, 
                sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE);
-        restore_flags(flags);
 }
 
 
@@ -1446,18 +1440,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;
 }
 
@@ -1584,11 +1578,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;) {
@@ -1634,7 +1628,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);
@@ -1696,7 +1690,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;
@@ -1721,7 +1715,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) {
@@ -1732,11 +1726,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;
 }
 
@@ -1761,7 +1755,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)) {
@@ -1795,13 +1789,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;
@@ -1811,11 +1805,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);
@@ -1850,7 +1844,7 @@
         }
         DPRINTK("After update2\n");
         dump_arp_table(priv);
-        lec_arp_unlock(priv);
+        lec_arp_put(priv);
 }
 
 /*
@@ -1864,7 +1858,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 */
 
@@ -1873,7 +1867,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);
@@ -1882,7 +1876,7 @@
 #endif
                 entry = make_entry(priv, bus_mac);
                 if (entry == NULL) {
-                        lec_arp_unlock(priv);
+                        lec_arp_put(priv);
                         return;
                 }
                 del_timer(&entry->timer);
@@ -1891,7 +1885,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
@@ -1909,7 +1903,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);
@@ -1922,7 +1916,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;
         }
@@ -1981,7 +1975,7 @@
                 }
         }
         if (found_entry) {
-                lec_arp_unlock(priv);
+                lec_arp_put(priv);
                 DPRINTK("After vcc was added\n");
                 dump_arp_table(priv);
                 return;
@@ -1990,7 +1984,7 @@
            this vcc */
         entry = make_entry(priv, bus_mac);
         if (!entry) {
-                lec_arp_unlock(priv);
+                lec_arp_put(priv);
                 return;
         }
         entry->vcc = vcc;
@@ -2003,7 +1997,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);
 }
@@ -2049,10 +2043,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);
@@ -2062,8 +2056,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;
 }
 
@@ -2075,7 +2069,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;
@@ -2137,7 +2131,7 @@
                 entry = next;
         }
 
-        lec_arp_unlock(priv);
+        lec_arp_put(priv);
 	dump_arp_table(priv);
 }
 
@@ -2145,9 +2139,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;
@@ -2157,26 +2151,26 @@
 #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) {
@@ -2185,22 +2179,21 @@
         }
         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.21-bk10/net/atm/lec.h linux-2.4.21-bk11/net/atm/lec.h
--- linux-2.4.21-bk10/net/atm/lec.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/lec.h	2003-07-16 02:53:56.000000000 -0700
@@ -101,7 +101,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;
diff -urN linux-2.4.21-bk10/net/atm/mpc.c linux-2.4.21-bk11/net/atm/mpc.c
--- linux-2.4.21-bk10/net/atm/mpc.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/mpc.c	2003-07-16 02:53:56.000000000 -0700
@@ -736,22 +736,15 @@
 }
 
 static struct atmdev_ops mpc_ops = { /* only send is required */
-	close:	mpoad_close,
-	send:	msg_from_mpoad
+	.close	= mpoad_close,
+	.send	= msg_from_mpoad
 };
 
 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               */
+	.ops	= &mpc_ops,
+	.type	= "mpc",
+	.number	= 42,
+	.lock	= SPIN_LOCK_UNLOCKED
 	/* rest of the members will be 0 */
 };
 
diff -urN linux-2.4.21-bk10/net/atm/proc.c linux-2.4.21-bk11/net/atm/proc.c
--- linux-2.4.21-bk10/net/atm/proc.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/proc.c	2003-07-16 02:53:56.000000000 -0700
@@ -84,6 +84,7 @@
 	add_stats(buf,"0",&dev->stats.aal0);
 	strcat(buf,"  ");
 	add_stats(buf,"5",&dev->stats.aal5);
+	sprintf(strchr(buf,0), "\t[%d]", atomic_read(&dev->refcnt));
 	strcat(buf,"\n");
 }
 
@@ -161,7 +162,7 @@
 #endif
 
 
-static void pvc_info(struct atm_vcc *vcc,char *buf)
+static void pvc_info(struct atm_vcc *vcc, char *buf, int clip_info)
 {
 	static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
 	static const char *aal_name[] = {
@@ -178,20 +179,17 @@
 	    class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
 	    class_name[vcc->qos.txtp.traffic_class]);
 #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-	if (try_atm_clip_ops()) {
-		if (vcc->push == atm_clip_ops->clip_push) {
-			struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
-			struct net_device *dev;
-
-			dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
-			off += sprintf(buf+off,"CLIP, Itf:%s, Encap:",
-			    dev ? dev->name : "none?");
-			if (clip_vcc->encap)
-				off += sprintf(buf+off,"LLC/SNAP");
-			else
-				off += sprintf(buf+off,"None");
-		}
-		__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+	if (clip_info && (vcc->push == atm_clip_ops->clip_push)) {
+		struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
+		struct net_device *dev;
+
+		dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
+		off += sprintf(buf+off,"CLIP, Itf:%s, Encap:",
+		    dev ? dev->name : "none?");
+		if (clip_vcc->encap)
+			off += sprintf(buf+off,"LLC/SNAP");
+		else
+			off += sprintf(buf+off,"None");
 	}
 #endif
 	strcpy(buf+off,"\n");
@@ -312,16 +310,19 @@
 
 	if (!pos) {
 		return sprintf(buf,"Itf Type    ESI/\"MAC\"addr "
-		    "AAL(TX,err,RX,err,drop) ...\n");
+		    "AAL(TX,err,RX,err,drop) ...               [refcnt]\n");
 	}
 	left = pos-1;
+	spin_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);
+			spin_unlock(&atm_dev_lock);
 			return strlen(buf);
 		}
 	}
+	spin_unlock(&atm_dev_lock);
 	return 0;
 }
 
@@ -332,31 +333,50 @@
 
 static int atm_pvc_info(loff_t pos,char *buf)
 {
+	unsigned long flags;
 	struct atm_dev *dev;
 	struct list_head *p;
 	struct atm_vcc *vcc;
-	int left;
+	int left, clip_info = 0;
 
 	if (!pos) {
 		return sprintf(buf,"Itf VPI VCI   AAL RX(PCR,Class) "
 		    "TX(PCR,Class)\n");
 	}
 	left = pos-1;
+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+	if (try_atm_clip_ops())
+		clip_info = 1;
+#endif
+	spin_lock(&atm_dev_lock);
 	list_for_each(p, &atm_devs) {
 		dev = list_entry(p, struct atm_dev, dev_list);
+		spin_lock_irqsave(&dev->lock, flags);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
-			if (vcc->sk->family == PF_ATMPVC &&
-			    vcc->dev && !left--) {
-				pvc_info(vcc,buf);
+			if (vcc->sk->family == PF_ATMPVC && vcc->dev && !left--) {
+				pvc_info(vcc,buf,clip_info);
+				spin_unlock_irqrestore(&dev->lock, flags);
+				spin_unlock(&atm_dev_lock);
+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+				if (clip_info)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+#endif
 				return strlen(buf);
 			}
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
+	spin_unlock(&atm_dev_lock);
+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+	if (clip_info)
+		__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+#endif
 	return 0;
 }
 
 
 static int atm_vc_info(loff_t pos,char *buf)
 {
+	unsigned long flags;
 	struct atm_dev *dev;
 	struct list_head *p;
 	struct atm_vcc *vcc;
@@ -367,19 +387,20 @@
 		    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
 		    "     Recv buffer\n");
 	left = pos-1;
+	spin_lock(&atm_dev_lock);
 	list_for_each(p, &atm_devs) {
 		dev = list_entry(p, struct atm_dev, dev_list);
+		spin_lock_irqsave(&dev->lock, flags);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
 			if (!left--) {
 				vc_info(vcc,buf);
+				spin_unlock_irqrestore(&dev->lock, flags);
+				spin_unlock(&atm_dev_lock);
 				return strlen(buf);
 			}
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
-	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
-		if (!left--) {
-			vc_info(vcc,buf);
-			return strlen(buf);
-		}
+	spin_unlock(&atm_dev_lock);
 
 	return 0;
 }
@@ -387,6 +408,7 @@
 
 static int atm_svc_info(loff_t pos,char *buf)
 {
+	unsigned long flags;
 	struct atm_dev *dev;
 	struct list_head *p;
 	struct atm_vcc *vcc;
@@ -395,19 +417,21 @@
 	if (!pos)
 		return sprintf(buf,"Itf VPI VCI           State      Remote\n");
 	left = pos-1;
+	spin_lock(&atm_dev_lock);
 	list_for_each(p, &atm_devs) {
 		dev = list_entry(p, struct atm_dev, dev_list);
+		spin_lock_irqsave(&dev->lock, flags);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
 			if (vcc->sk->family == PF_ATMSVC && !left--) {
 				svc_info(vcc,buf);
+				spin_unlock_irqrestore(&dev->lock, flags);
+				spin_unlock(&atm_dev_lock);
 				return strlen(buf);
 			}
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
-	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
-		if (vcc->sk->family == PF_ATMSVC && !left--) {
-			svc_info(vcc,buf);
-			return strlen(buf);
-		}
+	spin_unlock(&atm_dev_lock);
+
 	return 0;
 }
 
@@ -608,12 +632,28 @@
     name->proc_fops = &proc_spec_atm_operations; \
     name->owner = THIS_MODULE
 
+static struct proc_dir_entry *devices = NULL, *pvc = NULL,
+		*svc = NULL, *arp = NULL, *lec = NULL, *vc = NULL;
 
-int __init atm_proc_init(void)
+static void atm_proc_cleanup(void)
 {
-	struct proc_dir_entry *devices = NULL,*pvc = NULL,*svc = NULL;
-	struct proc_dir_entry *arp = NULL,*lec = NULL,*vc = NULL;
+	if (devices)
+		remove_proc_entry("devices",atm_proc_root);
+	if (pvc)
+		remove_proc_entry("pvc",atm_proc_root);
+	if (svc)
+		remove_proc_entry("svc",atm_proc_root);
+	if (arp)
+		remove_proc_entry("arp",atm_proc_root);
+	if (lec)
+		remove_proc_entry("lec",atm_proc_root);
+	if (vc)
+		remove_proc_entry("vc",atm_proc_root);
+	remove_proc_entry("net/atm",NULL);
+}
 
+int atm_proc_init(void)
+{
 	atm_proc_root = proc_mkdir("net/atm",NULL);
 	if (!atm_proc_root)
 		return -ENOMEM;
@@ -630,12 +670,11 @@
 	return 0;
 
 cleanup:
-	if (devices) remove_proc_entry("devices",atm_proc_root);
-	if (pvc) remove_proc_entry("pvc",atm_proc_root);
-	if (svc) remove_proc_entry("svc",atm_proc_root);
-	if (arp) remove_proc_entry("arp",atm_proc_root);
-	if (lec) remove_proc_entry("lec",atm_proc_root);
-	if (vc) remove_proc_entry("vc",atm_proc_root);
-	remove_proc_entry("net/atm",NULL);
+	atm_proc_cleanup();
 	return -ENOMEM;
 }
+
+void atm_proc_exit(void)
+{
+	atm_proc_cleanup();
+}
diff -urN linux-2.4.21-bk10/net/atm/pvc.c linux-2.4.21-bk11/net/atm/pvc.c
--- linux-2.4.21-bk10/net/atm/pvc.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/pvc.c	2003-07-16 02:53:56.000000000 -0700
@@ -120,20 +120,12 @@
  */
 
 
-static int __init atmpvc_init(void)
+int atmpvc_init(void)
 {
-	int error;
-
-	error = sock_register(&pvc_family_ops);
-	if (error < 0) {
-		printk(KERN_ERR "ATMPVC: can't register (%d)",error);
-		return error;
-	}
-#ifdef CONFIG_PROC_FS
-	error = atm_proc_init();
-	if (error) printk("atm_proc_init fails with %d\n",error);
-#endif
-	return 0;
+	return sock_register(&pvc_family_ops);
 }
 
-module_init(atmpvc_init);
+void atmpvc_exit(void)
+{
+	sock_unregister(PF_ATMPVC);
+}
diff -urN linux-2.4.21-bk10/net/atm/resources.c linux-2.4.21-bk11/net/atm/resources.c
--- linux-2.4.21-bk10/net/atm/resources.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/resources.c	2003-07-16 02:53:56.000000000 -0700
@@ -23,67 +23,83 @@
 
 
 LIST_HEAD(atm_devs);
-struct atm_vcc *nodev_vccs = NULL;
-extern spinlock_t atm_dev_lock;
+spinlock_t atm_dev_lock = SPIN_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);
+	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;
 
 	spin_lock(&atm_dev_lock);
+	dev = __atm_dev_lookup(number);
+	spin_unlock(&atm_dev_lock);
+	return dev;
+}
 
-	dev = alloc_atm_dev(type);
+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;
 	}
+	spin_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);
+			spin_unlock(&atm_dev_lock);
+			__free_atm_dev(dev);
 			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;
@@ -92,41 +108,66 @@
 	if (flags) 
 		dev->flags = *flags;
 	else 
-		memset(&dev->flags,0,sizeof(dev->flags));
-	memset((void *) &dev->stats,0,sizeof(dev->stats));
+		memset(&dev->flags, 0, sizeof(dev->flags));
+	memset(&dev->stats, 0, sizeof(dev->stats));
+	atomic_set(&dev->refcnt, 1);
+	list_add_tail(&dev->dev_list, &atm_devs);
+	spin_unlock(&atm_dev_lock);
+
 #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);
+			spin_lock(&atm_dev_lock);
+			list_del(&dev->dev_list);
+			spin_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);
 #endif
 	spin_lock(&atm_dev_lock);
-	free_atm_dev(dev);
+	list_del(&dev->dev_list);
 	spin_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;
+		}
+	}
+
+	__free_atm_dev(dev);
 }
 
 void shutdown_atm_dev(struct atm_dev *dev)
 {
-	if (dev->vccs) {
-		set_bit(ATM_DF_CLOSE,&dev->flags);
+	if (atomic_read(&dev->refcnt) > 1) {
+		set_bit(ATM_DF_CLOSE, &dev->flags);
 		return;
 	}
-	if (dev->ops->dev_close) dev->ops->dev_close(dev);
+	if (dev->ops->dev_close)
+		dev->ops->dev_close(dev);
 	atm_dev_deregister(dev);
 }
 
@@ -143,66 +184,69 @@
 	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 (!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);
+	sock_init_data(NULL, sk);
 	sk->destruct = atm_free_sock;
-	memset(vcc,0,sizeof(*vcc));
+	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)
+static void unlink_vcc(struct atm_vcc *vcc)
 {
-	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);
+	unsigned long flags;
+	if (vcc->dev) {
+		spin_lock_irqsave(&vcc->dev->lock, flags);
+		if (vcc->prev)
+			vcc->prev->next = vcc->next;
+		else
+			vcc->dev->vccs = vcc->next;
+
+		if (vcc->next)
+			vcc->next->prev = vcc->prev;
+		else
+			vcc->dev->last = vcc->prev;
+		spin_unlock_irqrestore(&vcc->dev->lock, flags);
+	}
 }
 
 
+
 void free_atm_vcc_sk(struct sock *sk)
 {
-	unlink_vcc(sk->protinfo.af_atm,NULL);
+	unlink_vcc(sk->protinfo.af_atm);
 	sk_free(sk);
 }
 
 
 void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev)
 {
-	unlink_vcc(vcc,dev);
+	unsigned long flags;
+
+	unlink_vcc(vcc);
 	vcc->dev = dev;
 	if (dev) {
+		spin_lock_irqsave(&dev->lock, flags);
 		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;
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
 }
 
 
 EXPORT_SYMBOL(atm_dev_register);
 EXPORT_SYMBOL(atm_dev_deregister);
-EXPORT_SYMBOL(atm_find_dev);
+EXPORT_SYMBOL(atm_dev_lookup);
 EXPORT_SYMBOL(shutdown_atm_dev);
 EXPORT_SYMBOL(bind_vcc);
diff -urN linux-2.4.21-bk10/net/atm/resources.h linux-2.4.21-bk11/net/atm/resources.h
--- linux-2.4.21-bk10/net/atm/resources.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/resources.h	2003-07-16 02:53:56.000000000 -0700
@@ -11,7 +11,7 @@
 
 
 extern struct list_head atm_devs;
-extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */
+extern spinlock_t atm_dev_lock;
 
 
 struct sock *alloc_atm_vcc_sk(int family);
diff -urN linux-2.4.21-bk10/net/atm/signaling.c linux-2.4.21-bk11/net/atm/signaling.c
--- linux-2.4.21-bk10/net/atm/signaling.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/signaling.c	2003-07-16 02:53:56.000000000 -0700
@@ -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)
 {
@@ -211,6 +210,7 @@
 
 static void sigd_close(struct atm_vcc *vcc)
 {
+	unsigned long flags;
 	struct atm_dev *dev;
 	struct list_head *p;
 
@@ -219,33 +219,29 @@
 	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);
+	spin_lock(&atm_dev_lock);
 	list_for_each(p, &atm_devs) {
 		dev = list_entry(p, struct atm_dev, dev_list);
+		spin_lock_irqsave(&dev->lock, flags);
 		purge_vccs(dev->vccs);
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
-	spin_unlock (&atm_dev_lock);
+	spin_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,
+	.type =		"sig",
+	.number =	999,
+	.lock =		SPIN_LOCK_UNLOCKED
 };
 
 
diff -urN linux-2.4.21-bk10/net/atm/svc.c linux-2.4.21-bk11/net/atm/svc.c
--- linux-2.4.21-bk10/net/atm/svc.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/atm/svc.c	2003-07-16 02:53:56.000000000 -0700
@@ -443,13 +443,12 @@
  *	Initialize the ATM SVC protocol family
  */
 
-static int __init atmsvc_init(void)
+int atmsvc_init(void)
 {
-	if (sock_register(&svc_family_ops) < 0) {
-		printk(KERN_ERR "ATMSVC: can't register");
-		return -1;
-	}
-	return 0;
+	return sock_register(&svc_family_ops);
 }
 
-module_init(atmsvc_init);
+void atmsvc_exit(void)
+{
+	sock_unregister(PF_ATMSVC);
+}
diff -urN linux-2.4.21-bk10/net/ipv4/igmp.c linux-2.4.21-bk11/net/ipv4/igmp.c
--- linux-2.4.21-bk10/net/ipv4/igmp.c	2003-07-16 02:53:50.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv4/igmp.c	2003-07-16 02:53:56.000000000 -0700
@@ -1049,17 +1049,19 @@
 	reporter = im->reporter;
 	igmp_stop_timer(im);
 
-	if (IGMP_V1_SEEN(in_dev))
-		goto done;
-	if (IGMP_V2_SEEN(in_dev)) {
-		if (reporter)
-			igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
-		goto done;
-	}
-	/* IGMPv3 */
-	igmpv3_add_delrec(in_dev, im);
+	if (in_dev->dev->flags & IFF_UP) {
+		if (IGMP_V1_SEEN(in_dev))
+			goto done;
+		if (IGMP_V2_SEEN(in_dev)) {
+			if (reporter)
+				igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
+			goto done;
+		}
+		/* IGMPv3 */
+		igmpv3_add_delrec(in_dev, im);
 
-	igmp_ifc_event(in_dev);
+		igmp_ifc_event(in_dev);
+	}
 done:
 #endif
 	ip_mc_clear_src(im);
diff -urN linux-2.4.21-bk10/net/ipv4/raw.c linux-2.4.21-bk11/net/ipv4/raw.c
--- linux-2.4.21-bk10/net/ipv4/raw.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv4/raw.c	2003-07-16 02:53:56.000000000 -0700
@@ -360,7 +360,7 @@
 		 * IP_HDRINCL is much more convenient.
 		 */
 	} else {
-		err = -EINVAL;
+		err = -EDESTADDRREQ;
 		if (sk->state != TCP_ESTABLISHED) 
 			goto out;
 		daddr = sk->daddr;
diff -urN linux-2.4.21-bk10/net/ipv4/udp.c linux-2.4.21-bk11/net/ipv4/udp.c
--- linux-2.4.21-bk10/net/ipv4/udp.c	2003-07-16 02:53:51.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv4/udp.c	2003-07-16 02:53:56.000000000 -0700
@@ -480,7 +480,7 @@
 			return -EINVAL;
 	} else {
 		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			return -EDESTADDRREQ;
 		ufh.daddr = sk->daddr;
 		ufh.uh.dest = sk->dport;
 		/* Open fast path for connected socket.
diff -urN linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_LOG.c
--- linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_LOG.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_LOG.c	2003-07-16 02:53:56.000000000 -0700
@@ -89,7 +89,7 @@
 	printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
 
 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
-	printk("LEN=%u TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+	printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
 	       ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
 	       (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
 	       ipv6h->hop_limit,
diff -urN linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_ah.c linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_ah.c
--- linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_ah.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_ah.c	2003-07-16 02:53:56.000000000 -0700
@@ -134,7 +134,7 @@
        		return 0;
        }
 
-       ah=skb->data+ptr;
+       ah = (struct ahhdr *) (skb->data + ptr);
 
        DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
        DEBUGP("RES %04X ", ah->reserved);
diff -urN linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_esp.c linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_esp.c
--- linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_esp.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_esp.c	2003-07-16 02:53:56.000000000 -0700
@@ -124,7 +124,7 @@
        		return 0;
        }
 
-	esp=skb->data+ptr;
+	esp = (struct esphdr *) (skb->data + ptr);
 
 	DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
 
diff -urN linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_frag.c linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_frag.c
--- linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_frag.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_frag.c	2003-07-16 02:53:56.000000000 -0700
@@ -148,7 +148,7 @@
        		return 0;
        }
 
-       frag=skb->data+ptr;
+       frag = (struct fraghdr *) (skb->data + ptr);
 
        DEBUGP("IPv6 FRAG LEN %u %u ", hdrlen, frag->hdrlen);
        DEBUGP("INFO %04X ", frag->info);
diff -urN linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_ipv6header.c linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_ipv6header.c
--- linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_ipv6header.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_ipv6header.c	2003-07-16 02:53:56.000000000 -0700
@@ -19,12 +19,6 @@
 MODULE_DESCRIPTION("IPv6 headers match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int
 ipv6header_match(const struct sk_buff *skb,
 		 const struct net_device *in,
@@ -40,10 +34,8 @@
 	int len;
 	u8 nexthdr;
 	unsigned int ptr;
-        struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
 
 	/* Make sure this isn't an evil packet */
-	DEBUGP("ipv6_header entered \n");
 
 	/* type of the 1st exthdr */
 	nexthdr = skb->nh.ipv6h->nexthdr;
@@ -53,44 +45,10 @@
 	len = skb->len - ptr;
 	temp = 0;
 
-	DEBUGP("ipv6_header nexthdr %02X \n",nexthdr);
-	DEBUGP("ipv6_header ptr %08X \n",ptr);
-	DEBUGP("ipv6_header skblen %04X \n",skb->len);
-	DEBUGP("ipv6_header skbdatalen %04X \n",skb->data_len);
-	DEBUGP("ipv6_header len %04X \n",len);
-#if 0
-	for (temp=0;temp<skb->len;temp++){
-		if (!(temp % 16 )) DEBUGP("\nipv6_header data ");
-		DEBUGP("%02X ",skb->data[temp]);
-	}
-#endif
-	DEBUGP("\nipv6_header h.raw %02X %02X %02X %02X \n",
-			skb->h.raw[0],
-			skb->h.raw[1],
-			skb->h.raw[2],
-			skb->h.raw[3]);
-	DEBUGP("ipv6_header nh.raw %02X %02X %02X %02X \n",
-			skb->nh.raw[0],
-			skb->nh.raw[1],
-			skb->nh.raw[2],
-			skb->nh.raw[3]);
-	DEBUGP("ipv6_header CB %02X %02X %02X %02X %02X %02X %02X \n",
-			opt->iif,
-			opt->ra,
-			opt->hop,
-			opt->auth,
-			opt->dst0,
-			opt->srcrt,
-			opt->dst1);
-
-	temp = 0;
-
         while (ip6t_ext_hdr(nexthdr)) {
         	struct ipv6_opt_hdr *hdr;
         	int hdrlen;
 
-		DEBUGP("ipv6_header header iteration \n");
-
 		/* Is there enough space for the next ext header? */
                 if (len < (int)sizeof(struct ipv6_opt_hdr))
                         return 0;
@@ -115,8 +73,6 @@
                 else
                         hdrlen = ipv6_optlen(hdr);
 
-		DEBUGP("ipv6_header hdrlen %04X \n",hdrlen);
-
 		/* set the flag */
 		switch (nexthdr){
 			case NEXTHDR_HOP:
@@ -135,7 +91,6 @@
 				temp |= MASK_DSTOPTS;
 				break;
 			default:
-				DEBUGP("IPV6HEADER match: unknown nextheader %u\n",nexthdr);
 				return 0;
 				break;
 		}
@@ -144,7 +99,6 @@
                 len -= hdrlen;
                 ptr += hdrlen;
 		if ( ptr > skb->len ) {
-			DEBUGP("ipv6_header new ptr %04X \n",ptr);
 			break;
 		}
         }
@@ -152,8 +106,6 @@
 	if ( (nexthdr != NEXTHDR_NONE ) && (nexthdr != NEXTHDR_ESP) )
 		temp |= MASK_PROTO;
 
-	DEBUGP ("ipv6header: %02X %02X \n", temp, info->matchflags);
-
 	if (info->modeflag)
 		return (!( (temp & info->matchflags)
 			^ info->matchflags) ^ info->invflags);
@@ -171,8 +123,6 @@
 	/* Check for obvious errors */
 	/* This match is valid in all hooks! */
 	if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) {
-		DEBUGP("ip6t_ipv6header: matchsize != %u\n",
-			 IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)));
 		return 0;
 	}
 
diff -urN linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_rt.c linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_rt.c
--- linux-2.4.21-bk10/net/ipv6/netfilter/ip6t_rt.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/netfilter/ip6t_rt.c	2003-07-16 02:53:56.000000000 -0700
@@ -131,7 +131,7 @@
        		return 0;
        }
 
-       route=skb->data+ptr;
+       route = (struct ipv6_rt_hdr *) (skb->data + ptr);
 
        DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen);
        DEBUGP("TYPE %04X ", route->type);
diff -urN linux-2.4.21-bk10/net/ipv6/raw.c linux-2.4.21-bk11/net/ipv6/raw.c
--- linux-2.4.21-bk10/net/ipv6/raw.c	2003-07-16 02:53:51.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/raw.c	2003-07-16 02:53:56.000000000 -0700
@@ -573,7 +573,7 @@
 			fl.oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->state != TCP_ESTABLISHED) 
-			return(-EINVAL);
+			return -EDESTADDRREQ;
 		
 		proto = sk->num;
 		daddr = &(sk->net_pinfo.af_inet6.daddr);
diff -urN linux-2.4.21-bk10/net/ipv6/udp.c linux-2.4.21-bk11/net/ipv6/udp.c
--- linux-2.4.21-bk10/net/ipv6/udp.c	2003-07-16 02:53:51.000000000 -0700
+++ linux-2.4.21-bk11/net/ipv6/udp.c	2003-07-16 02:53:56.000000000 -0700
@@ -838,7 +838,7 @@
 			fl.oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			return -EDESTADDRREQ;
 
 		udh.uh.dest = sk->dport;
 		daddr = &sk->net_pinfo.af_inet6.daddr;
diff -urN linux-2.4.21-bk10/net/netlink/af_netlink.c linux-2.4.21-bk11/net/netlink/af_netlink.c
--- linux-2.4.21-bk10/net/netlink/af_netlink.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/netlink/af_netlink.c	2003-07-16 02:53:56.000000000 -0700
@@ -420,6 +420,11 @@
 	if (sk == NULL)
 		goto no_dst;
 
+	/* Don't bother queuing skb if kernel socket has no input function */
+	if (sk->protinfo.af_netlink->pid == 0 &&
+	    !sk->protinfo.af_netlink->data_ready)
+		goto no_dst;
+
 #ifdef NL_EMULATE_DEV
 	if (sk->protinfo.af_netlink->handler) {
 		skb_orphan(skb);
diff -urN linux-2.4.21-bk10/net/netsyms.c linux-2.4.21-bk11/net/netsyms.c
--- linux-2.4.21-bk10/net/netsyms.c	2003-07-16 02:53:51.000000000 -0700
+++ linux-2.4.21-bk11/net/netsyms.c	2003-07-16 02:53:56.000000000 -0700
@@ -163,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);
diff -urN linux-2.4.21-bk10/net/sched/Config.in linux-2.4.21-bk11/net/sched/Config.in
--- linux-2.4.21-bk10/net/sched/Config.in	2002-11-28 15:53:16.000000000 -0800
+++ linux-2.4.21-bk11/net/sched/Config.in	2003-07-16 02:53:56.000000000 -0700
@@ -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.21-bk10/net/socket.c linux-2.4.21-bk11/net/socket.c
--- linux-2.4.21-bk10/net/socket.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.21-bk11/net/socket.c	2003-07-16 02:53:56.000000000 -0700
@@ -1359,7 +1359,7 @@
 		goto out;
 
 	/* do not move before msg_sys is valid */
-	err = -EINVAL;
+	err = -EMSGSIZE;
 	if (msg_sys.msg_iovlen > UIO_MAXIOV)
 		goto out_put;
 
@@ -1442,7 +1442,7 @@
 	if (!sock)
 		goto out;
 
-	err = -EINVAL;
+	err = -EMSGSIZE;
 	if (msg_sys.msg_iovlen > UIO_MAXIOV)
 		goto out_put;
 	
diff -urN linux-2.4.21-bk10/net/sunrpc/svcsock.c linux-2.4.21-bk11/net/sunrpc/svcsock.c
--- linux-2.4.21-bk10/net/sunrpc/svcsock.c	2003-07-16 02:53:51.000000000 -0700
+++ linux-2.4.21-bk11/net/sunrpc/svcsock.c	2003-07-16 02:53:57.000000000 -0700
@@ -826,7 +826,7 @@
 			goto error;
 		svsk->sk_tcplen += len;
 		if (len < want) {
-			dprintk("svc: short recvfrom while reading record length (%d of %d)\n",
+			dprintk("svc: short recvfrom while reading record length (%d of %ld)\n",
 			        len, want);
 			svc_sock_received(svsk);
 			return -EAGAIN; /* record header not complete */
