Index: natm.c
===================================================================
RCS file: /home/ncvs/src/sys/netnatm/natm.c,v
retrieving revision 1.37
diff -u -r1.37 natm.c
--- natm.c	7 Jan 2005 01:45:48 -0000	1.37
+++ natm.c	30 May 2005 10:20:01 -0000
@@ -67,6 +67,8 @@
 static const u_long natm0_sendspace = 16*1024;
 static const u_long natm0_recvspace = 16*1024;
 
+struct mtx natm_mtx;
+
 /*
  * user requests
  */
@@ -93,14 +95,10 @@
 {
     struct natmpcb *npcb;
     int error = 0;
-    int s = SPLSOFTNET();
 
     npcb = (struct natmpcb *)so->so_pcb;
 
-    if (npcb) {
-	error = EISCONN;
-	goto out;
-    }
+    KASSERT(npcb == NULL, ("natm_usr_attach: so_pcb != NULL"));
 
     if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
 	if (proto == PROTO_NATMAAL5) 
@@ -113,8 +111,7 @@
 
     so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
     npcb->npcb_socket = so;
- out:
-    splx(s);
+out:
     return (error);
 }
 
@@ -123,10 +120,11 @@
 {
     struct natmpcb *npcb;
     int error = 0;
-    int s = SPLSOFTNET();
 
+    NATM_LOCK();
     npcb = (struct natmpcb *)so->so_pcb;
     if (npcb == NULL) {
+	/* XXXRW: Does this case ever actually happen? */
 	error = EINVAL;
 	goto out;
     }
@@ -140,7 +138,7 @@
     so->so_pcb = NULL;
     sotryfree(so);
  out:
-    splx(s);
+    NATM_UNLOCK();
     return (error);
 }
 
@@ -152,11 +150,12 @@
     struct atmio_openvcc op;
     struct ifnet *ifp;
     int error = 0;
-    int s2, s = SPLSOFTNET();
     int proto = so->so_proto->pr_protocol;
 
+    NATM_LOCK();
     npcb = (struct natmpcb *)so->so_pcb;
     if (npcb == NULL) {
+	/* XXXRW: Does this case ever actually happen? */
 	error = EINVAL;
 	goto out;
     }
@@ -198,6 +197,7 @@
         error = EADDRINUSE;
         goto out;
     }
+    NATM_UNLOCK();
 
     /*
      * open the channel
@@ -211,20 +211,19 @@
     op.param.aal = (proto == PROTO_NATMAAL5) ? ATMIO_AAL_5 : ATMIO_AAL_0;
     op.param.traffic = ATMIO_TRAFFIC_UBR;
 
-    s2 = splimp();
     if (ifp->if_ioctl == NULL || 
 	ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0) {
-	splx(s2);
+	NATM_UNLOCK();
 	npcb_free(npcb, NPCB_REMOVE);
         error = EIO;
 	goto out;
     }
-    splx(s2);
 
+    NATM_LOCK();
     soisconnected(so);
 
  out:
-    splx(s);
+    NATM_UNLOCK();
     return (error);
 }
 
@@ -235,10 +234,11 @@
     struct atmio_closevcc cl;
     struct ifnet *ifp;
     int error = 0;
-    int s2, s = SPLSOFTNET();
 
+    NATM_LOCK();
     npcb = (struct natmpcb *)so->so_pcb;
     if (npcb == NULL) {
+	/* XXXRW: Does this case ever actually happen? */
 	error = EINVAL;
 	goto out;
     }
@@ -255,16 +255,16 @@
      */
     cl.vpi = npcb->npcb_vpi;
     cl.vci = npcb->npcb_vci;
-    s2 = splimp();
+    NATM_UNLOCK();
     if (ifp->if_ioctl != NULL)
 	ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
-    splx(s2);
+    NATM_LOCK();
 
     npcb_free(npcb, NPCB_REMOVE);
     soisdisconnected(so);
 
  out:
-    splx(s);
+    NATM_UNLOCK();
     return (error);
 }
 
@@ -282,11 +282,12 @@
     struct natmpcb *npcb;
     struct atm_pseudohdr *aph;
     int error = 0;
-    int s = SPLSOFTNET();
     int proto = so->so_proto->pr_protocol;
 
+    NATM_LOCK();
     npcb = (struct natmpcb *)so->so_pcb;
     if (npcb == NULL) {
+	/* XXXRW: Does this case ever actually happen? */
 	error = EINVAL;
 	goto out;
     }
@@ -314,7 +315,7 @@
     error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
 
  out:
-    splx(s);
+    NATM_UNLOCK();
     return (error);
 }
 
@@ -323,13 +324,13 @@
 {
     struct natmpcb *npcb;
     struct sockaddr_natm *snatm, ssnatm;
-    int error = 0;
-    int s = SPLSOFTNET();
 
+    NATM_LOCK();
     npcb = (struct natmpcb *)so->so_pcb;
     if (npcb == NULL) {
-	error = EINVAL;
-	goto out;
+	/* XXXRW: Does this case ever actually happen? */
+    	NATM_UNLOCK();
+	return (EINVAL);
     }
 
     snatm = &ssnatm;
@@ -340,11 +341,9 @@
         sizeof(snatm->snatm_if));
     snatm->snatm_vci = npcb->npcb_vci;
     snatm->snatm_vpi = npcb->npcb_vpi;
-    *nam = sodupsockaddr((struct sockaddr *)snatm, M_NOWAIT);
-
- out:
-    splx(s);
-    return (error);
+    NATM_UNLOCK();
+    *nam = sodupsockaddr((struct sockaddr *)snatm, M_WAITOK);
+    return (0);
 }
 
 static int
@@ -352,25 +351,18 @@
     struct ifnet *ifp, d_thread_t *p)
 {
     struct natmpcb *npcb;
-    int error = 0;
-    int s = SPLSOFTNET();
 
+    /*
+     * XXXRW: Does this case ever actually happen?  And does it even matter
+     * given that npcb is unused?
+     */
     npcb = (struct natmpcb *)so->so_pcb;
-    if (npcb == NULL) {
-	error = EINVAL;
-	goto out;
-    }
+    if (npcb == NULL)
+	return (EINVAL);
 
-    splx(s);
-    if (ifp == NULL || ifp->if_ioctl == NULL) {
-	error = EOPNOTSUPP;
-	goto out;
-    }
+    if (ifp == NULL || ifp->if_ioctl == NULL)
+	return (EOPNOTSUPP);
     return ((*ifp->if_ioctl)(ifp, cmd, arg));
-
- out:
-    splx(s);
-    return (error);
 }
 
 static int
@@ -407,6 +399,7 @@
 };
 
 #else  /* !FREEBSD_USRREQS */
+#error "!FREEBSD_USRREQS not implemented - locking"
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 int natm_usrreq(so, req, m, nam, control, p)
@@ -690,31 +683,29 @@
 void
 natmintr(struct mbuf *m)
 {
-	int s;
 	struct socket *so;
 	struct natmpcb *npcb;
 
-	GIANT_REQUIRED;
-
 #ifdef DIAGNOSTIC
 	M_ASSERTPKTHDR(m);
 #endif
 
+	NATM_LOCK();
 	npcb = (struct natmpcb *)m->m_pkthdr.rcvif;	/* XXX: overloaded */
 	so = npcb->npcb_socket;
 
-	s = splimp();		/* could have atm devs @ different levels */
 	npcb->npcb_inq--;
-	splx(s);
 
 	if (npcb->npcb_flags & NPCB_DRAIN) {
-		m_freem(m);
 		if (npcb->npcb_inq == 0)
 			FREE(npcb, M_PCB);			/* done! */
+		NATM_UNLOCK();
+		m_freem(m);
 		return;
 	}
 
 	if (npcb->npcb_flags & NPCB_FREE) {
+		NATM_UNLOCK();
 		m_freem(m);					/* drop */
 		return;
 	}
@@ -734,11 +725,13 @@
 #endif
 		sbappendrecord(&so->so_rcv, m);
 		sorwakeup(so);
+		NATM_UNLOCK();
 	} else {
 #ifdef NATM_STAT
 		natm_sodropcnt++;
 		natm_sodropbytes += m->m_pkthdr.len;
 #endif
+		NATM_UNLOCK();
 		m_freem(m);
 	}
 }
Index: natm.h
===================================================================
RCS file: /home/ncvs/src/sys/netnatm/natm.h,v
retrieving revision 1.10
diff -u -r1.10 natm.h
--- natm.h	7 Jan 2005 01:45:48 -0000	1.10
+++ natm.h	30 May 2005 10:08:17 -0000
@@ -95,6 +95,7 @@
 
 /* global data structures */
 
+extern struct mtx natm_mtx;		/* global netnatm lock */
 extern struct npcblist natm_pcbs;	/* global list of pcbs */
 #define	NATM_STAT
 #ifdef NATM_STAT
@@ -104,6 +105,12 @@
 extern	u_int	natm_sookbytes;		/* account of ok */
 #endif
 
+/* locking macros */
+#define	NATM_LOCK_INIT()	mtx_init(&natm_mtx, "natm_mtx", NULL, MTX_DEF)
+#define	NATM_LOCK()		mtx_lock(&natm_mtx)
+#define	NATM_UNLOCK()		mtx_unlock(&natm_mtx)
+#define	NATM_LOCK_ASSERT()	mtx_assert(&natm_mtx, MA_OWNED)
+
 /* external functions */
 
 /* natm_pcb.c */
Index: natm_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netnatm/natm_pcb.c,v
retrieving revision 1.15
diff -u -r1.15 natm_pcb.c
--- natm_pcb.c	7 Jan 2005 01:45:48 -0000	1.15
+++ natm_pcb.c	30 May 2005 10:08:51 -0000
@@ -81,7 +81,8 @@
 void
 npcb_free(struct natmpcb *npcb, int op)
 {
-	int s = splimp();
+
+	NATM_LOCK_ASSERT();
 
 	if ((npcb->npcb_flags & NPCB_FREE) == 0) {
 		LIST_REMOVE(npcb, pcblist);
@@ -94,8 +95,6 @@
 			FREE(npcb, M_PCB);		/* kill it! */
 		}
 	}
-
-	splx(s);
 }
 
 
@@ -107,8 +106,8 @@
 npcb_add(struct natmpcb *npcb, struct ifnet *ifp, u_int16_t vci, u_int8_t vpi)
 {
 	struct natmpcb *cpcb = NULL;		/* current pcb */
-	int s = splimp();
 
+	NATM_LOCK_ASSERT();
 
 	/*
 	 * lookup required
@@ -147,7 +146,6 @@
 	LIST_INSERT_HEAD(&natm_pcbs, cpcb, pcblist);
 
 done:
-	splx(s);
 	return (cpcb);
 }
 
Index: natm_proto.c
===================================================================
RCS file: /home/ncvs/src/sys/netnatm/natm_proto.c,v
retrieving revision 1.15
diff -u -r1.15 natm_proto.c
--- natm_proto.c	17 Feb 2005 14:21:22 -0000	1.15
+++ natm_proto.c	30 May 2005 10:20:51 -0000
@@ -56,8 +56,6 @@
 
 static	void natm_init(void);
 
-NET_NEEDS_GIANT("netnatm");
-
 static struct protosw natmsw[] = {
 { SOCK_STREAM,	&natmdomain,	PROTO_NATMAAL5, PR_CONNREQUIRED,
   0,	0,	0,	0,
@@ -123,6 +121,7 @@
 	LIST_INIT(&natm_pcbs);
 	bzero(&natmintrq, sizeof(natmintrq));
 	natmintrq.ifq_maxlen = natmqmaxlen;
+	NATM_LOCK_INIT();
 	mtx_init(&natmintrq.ifq_mtx, "natm_inq", NULL, MTX_DEF);
 	netisr_register(NETISR_NATM, natmintr, &natmintrq, 0);
 }
