Patch from chas williams <chas@locutus.cmf.nrl.navy.mil>

this patch changes the atm_dev_lock spinlock to a semaphore.  this
solves the sleeping while holding a spinlock problem.  none of the 
code paths doing the original locking are in_interrupt() so this is
fairly straight forward.




 atm/addr.c      |    1 -
 atm/common.c    |   21 +++++++++++----------
 atm/resources.c |   17 +++++++++--------
 atm/signaling.c |    7 ++++---
 4 files changed, 24 insertions(+), 22 deletions(-)

diff -puN net/atm/addr.c~atm_dev_sem net/atm/addr.c
--- 25/net/atm/addr.c~atm_dev_sem	2003-02-22 15:16:37.000000000 -0800
+++ 25-akpm/net/atm/addr.c	2003-02-22 15:16:37.000000000 -0800
@@ -42,7 +42,6 @@ static int identical(struct sockaddr_atm
  */
 
 static DECLARE_MUTEX(local_lock);
-extern  spinlock_t atm_dev_lock;
 
 static void notify_sigd(struct atm_dev *dev)
 {
diff -puN net/atm/common.c~atm_dev_sem net/atm/common.c
--- 25/net/atm/common.c~atm_dev_sem	2003-02-22 15:16:37.000000000 -0800
+++ 25-akpm/net/atm/common.c	2003-02-22 15:16:37.000000000 -0800
@@ -27,6 +27,7 @@
 #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>
@@ -79,7 +80,7 @@ EXPORT_SYMBOL(pppoatm_ioctl_hook);
 #define DPRINTK(format,args...)
 #endif
 
-spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
+DECLARE_MUTEX(atm_dev_sem);
 
 static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
 {
@@ -145,7 +146,7 @@ void atm_release_vcc_sk(struct sock *sk,
 				vcc->dev->ops->free_rx_skb(vcc,skb);
 			else kfree_skb(skb);
 		}
-		spin_lock (&atm_dev_lock);	
+		down(&atm_dev_sem);	
 		fops_put (vcc->dev->ops);
 		if (atomic_read(&vcc->rx_inuse))
 			printk(KERN_WARNING "atm_release_vcc: strange ... "
@@ -153,11 +154,11 @@ void atm_release_vcc_sk(struct sock *sk,
 			    atomic_read(&vcc->rx_inuse));
 		bind_vcc(vcc,NULL);
 	} else
-		spin_lock (&atm_dev_lock);	
+		down(&atm_dev_sem);	
 
 	if (free_sk) free_atm_vcc_sk(sk);
 
-	spin_unlock (&atm_dev_lock);
+	up(&atm_dev_sem);
 }
 
 
@@ -268,14 +269,14 @@ static int atm_do_connect(struct atm_vcc
 	struct atm_dev *dev;
 	int return_val;
 
-	spin_lock (&atm_dev_lock);
+	down(&atm_dev_sem);
 	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);
+	up(&atm_dev_sem);
 
 	return return_val;
 }
@@ -307,10 +308,10 @@ int atm_connect_vcc(struct atm_vcc *vcc,
 	else {
 		struct atm_dev *dev;
 
-		spin_lock (&atm_dev_lock);
+		down(&atm_dev_sem);
 		for (dev = atm_devs; dev; dev = dev->next)
 			if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
-		spin_unlock (&atm_dev_lock);
+		up(&atm_dev_sem);
 		if (!dev) return -ENODEV;
 	}
 	if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
@@ -552,7 +553,7 @@ int atm_ioctl(struct socket *sock,unsign
 	int error,len,size,number, ret_val;
 
 	ret_val = 0;
-	spin_lock (&atm_dev_lock);
+	down(&atm_dev_sem);
 	vcc = ATM_SD(sock);
 	switch (cmd) {
 		case SIOCOUTQ:
@@ -942,7 +943,7 @@ int atm_ioctl(struct socket *sock,unsign
 		ret_val = 0;
 
  done:
-	spin_unlock (&atm_dev_lock); 
+	up(&atm_dev_sem); 
 	return ret_val;
 }
 
diff -puN net/atm/resources.c~atm_dev_sem net/atm/resources.c
--- 25/net/atm/resources.c~atm_dev_sem	2003-02-22 15:16:37.000000000 -0800
+++ 25-akpm/net/atm/resources.c	2003-02-22 15:16:37.000000000 -0800
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <net/sock.h>	 /* for struct sock */
+#include <asm/semaphore.h>
 
 #include "common.h"
 #include "resources.h"
@@ -29,9 +30,9 @@
 struct atm_dev *atm_devs = NULL;
 static struct atm_dev *last_dev = NULL;
 struct atm_vcc *nodev_vccs = NULL;
-extern spinlock_t atm_dev_lock;
+extern struct semaphore atm_dev_sem;
 
-/* Caller must hold atm_dev_lock. */
+/* Caller must hold atm_dev_sem. */
 static struct atm_dev *__alloc_atm_dev(const char *type)
 {
 	struct atm_dev *dev;
@@ -56,7 +57,7 @@ static struct atm_dev *__alloc_atm_dev(c
 	return dev;
 }
 
-/* Caller must hold atm_dev_lock. */
+/* Caller must hold atm_dev_sem. */
 static void __free_atm_dev(struct atm_dev *dev)
 {
 	if (dev->prev)
@@ -70,7 +71,7 @@ static void __free_atm_dev(struct atm_de
 	kfree(dev);
 }
 
-/* Caller must hold atm_dev_lock. */
+/* Caller must hold atm_dev_sem. */
 struct atm_dev *atm_find_dev(int number)
 {
 	struct atm_dev *dev;
@@ -87,7 +88,7 @@ struct atm_dev *atm_dev_register(const c
 {
 	struct atm_dev *dev;
 
-	spin_lock(&atm_dev_lock);
+	down(&atm_dev_sem);
 
 	dev = __alloc_atm_dev(type);
 	if (!dev) {
@@ -131,7 +132,7 @@ struct atm_dev *atm_dev_register(const c
 #endif
 
 done:
-	spin_unlock(&atm_dev_lock);
+	up(&atm_dev_sem);
 	return dev;
 }
 
@@ -142,9 +143,9 @@ void atm_dev_deregister(struct atm_dev *
 	if (dev->ops->proc_read)
 		atm_proc_dev_deregister(dev);
 #endif
-	spin_lock(&atm_dev_lock);
+	down(&atm_dev_sem);
 	__free_atm_dev(dev);
-	spin_unlock(&atm_dev_lock);
+	up(&atm_dev_sem);
 }
 
 void shutdown_atm_dev(struct atm_dev *dev)
diff -puN net/atm/signaling.c~atm_dev_sem net/atm/signaling.c
--- 25/net/atm/signaling.c~atm_dev_sem	2003-02-22 15:16:37.000000000 -0800
+++ 25-akpm/net/atm/signaling.c	2003-02-22 15:16:37.000000000 -0800
@@ -13,6 +13,7 @@
 #include <linux/atmsvc.h>
 #include <linux/atmdev.h>
 #include <linux/bitops.h>
+#include <asm/semaphore.h>
 
 #include "resources.h"
 #include "signaling.h"
@@ -33,7 +34,7 @@
 struct atm_vcc *sigd = NULL;
 static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
 
-extern spinlock_t atm_dev_lock;
+extern struct semaphore atm_dev_sem;
 
 static void sigd_put_skb(struct sk_buff *skb)
 {
@@ -220,9 +221,9 @@ static void sigd_close(struct atm_vcc *v
 	skb_queue_purge(&vcc->recvq);
 	purge_vccs(nodev_vccs);
 
-	spin_lock (&atm_dev_lock);
+	down(&atm_dev_sem);
 	for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs);
-	spin_unlock (&atm_dev_lock);
+	up(&atm_dev_sem);
 }
 
 

_