Subject: Re: SMP re-entrancy in kernel drivers/"bottom half?"
To: None <jonathan@dsg.stanford.edu>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 12/30/2003 13:34:53
--NextPart-20031230132714-0843500
Content-Type: Text/Plain; charset=us-ascii

> >for your purpose, i think what you need are:
> >- change lowlevel intr handler (Xintr_* in the case of i386) not to
> >  take kernel_lock if the driver is marked as mp-safe.
> >- make the driver mp-safe.
> >	- change the driver to acquire per-device lock if needed.
> >	- change the driver to acquire kernel_lock
> >	  (or other fine-grained locks) when needed.

for someone interested..

YAMAMOTO Takashi


--NextPart-20031230132714-0843500
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="bkl3.diff"

Index: altq/if_altq.h
===================================================================
--- altq/if_altq.h	(revision 1)
+++ altq/if_altq.h	(working copy)
@@ -40,6 +40,7 @@ struct altq_pktattr; struct tb_regulator
  */
 struct	ifaltq {
 	/* fields compatible with struct ifqueue */
+	struct	simplelock ifq_slock;
 	struct	mbuf *ifq_head;
 	struct	mbuf *ifq_tail;
 	int	ifq_len;
Index: netinet/if_arp.c
===================================================================
--- netinet/if_arp.c	(revision 335)
+++ netinet/if_arp.c	(working copy)
@@ -153,7 +153,7 @@ static	void in_arpinput __P((struct mbuf
 extern	struct ifnet loif[NLOOP];
 #endif
 LIST_HEAD(, llinfo_arp) llinfo_arp;
-struct	ifqueue arpintrq = {0, 0, 0, 50};
+struct	ifqueue arpintrq = IFQ_INITIALIZER(50);
 int	arp_inuse, arp_allocated, arp_intimer;
 int	arp_maxtries = 5;
 int	useloopback = 1;	/* use loopback interface for local traffic */
@@ -761,7 +761,9 @@ arpintr()
 
 	while (arpintrq.ifq_head) {
 		s = splnet();
+		IFQ_LOCK(&arpintrq);
 		IF_DEQUEUE(&arpintrq, m);
+		IFQ_UNLOCK(&arpintrq);
 		splx(s);
 		if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
 			panic("arpintr");
Index: netinet/ip_input.c
===================================================================
--- netinet/ip_input.c	(revision 476)
+++ netinet/ip_input.c	(working copy)
@@ -417,6 +417,7 @@ ip_init()
 
 	ip_id = time.tv_sec & 0xfffff;
 
+	IFQ_INIT(&ipintrq);
 	ipintrq.ifq_maxlen = ipqmaxlen;
 	ip_nmbclusters_changed();
 
@@ -466,7 +467,9 @@ ipintr()
 
 	while (1) {
 		s = splnet();
+		IFQ_LOCK(&ipintrq);
 		IF_DEQUEUE(&ipintrq, m);
+		IFQ_UNLOCK(&ipintrq);
 		splx(s);
 		if (m == 0)
 			return;
Index: arch/i386/i386/vector.S
===================================================================
--- arch/i386/i386/vector.S	(revision 476)
+++ arch/i386/i386/vector.S	(working copy)
@@ -234,13 +234,6 @@ IDTVEC(intr_lapic_ltimer)
 	INTRFASTEXIT
 #endif /* NLAPIC > 0 */
 
-#ifdef MULTIPROCESSOR
-#define LOCK_KERNEL	pushl %esp ; call _C_LABEL(x86_intlock) ; addl $4,%esp
-#define UNLOCK_KERNEL	pushl %esp ; call _C_LABEL(x86_intunlock) ; addl $4,%esp
-#else
-#define LOCK_KERNEL
-#define UNLOCK_KERNEL
-#endif
 
 #define voidop(num)
 
@@ -286,7 +279,6 @@ IDTVEC(intr_/**/name/**/num)						;\
 	sti								;\
 	incl	CPUVAR(IDEPTH)						;\
 	movl	IS_HANDLERS(%ebp),%ebx					;\
-	LOCK_KERNEL							;\
 6:									\
 	movl	IH_LEVEL(%ebx),%edi					;\
 	cmpl	%esi,%edi						;\
@@ -299,14 +291,12 @@ IDTVEC(intr_/**/name/**/num)						;\
 	testl	%ebx,%ebx						;\
 	jnz	6b							;\
 5:									\
-	UNLOCK_KERNEL							;\
 	cli								;\
 	unmask(num)			/* unmask it in hardware */	;\
 	late_ack(num)							;\
 	sti								;\
 	jmp	_C_LABEL(Xdoreti)	/* lower spl and do ASTs */	;\
 7:									\
-	UNLOCK_KERNEL							;\
 	cli								;\
 	orl     $(1 << num),CPUVAR(IPENDING)				;\
 	level_mask(num)							;\
Index: arch/amd64/amd64/vector.S
===================================================================
--- arch/amd64/amd64/vector.S	(revision 294)
+++ arch/amd64/amd64/vector.S	(working copy)
@@ -371,13 +371,6 @@ IDTVEC(intr_lapic_ltimer)
 	INTRFASTEXIT
 #endif /* NLAPIC > 0 */
 
-#ifdef MULTIPROCESSOR
-#define LOCK_KERNEL	movq %rsp,%rdi ; call _C_LABEL(x86_intlock)
-#define UNLOCK_KERNEL	movq %rsp,%rdi ; call _C_LABEL(x86_intunlock)
-#else
-#define LOCK_KERNEL
-#define UNLOCK_KERNEL
-#endif
 
 #define voidop(num)
 
@@ -420,7 +413,6 @@ IDTVEC(intr_/**/name/**/num)						;\
 	sti								;\
 	incl	CPUVAR(IDEPTH)						;\
 	movq	IS_HANDLERS(%r14),%rbx					;\
-	LOCK_KERNEL							;\
 6:									\
 	movl	IH_LEVEL(%rbx),%r12d					;\
 	cmpl	%r13d,%r12d						;\
@@ -432,14 +424,12 @@ IDTVEC(intr_/**/name/**/num)						;\
 	testq	%rbx,%rbx						;\
 	jnz	6b							;\
 5:									\
-	UNLOCK_KERNEL							;\
 	cli								;\
 	unmask(num)			/* unmask it in hardware */	;\
 	late_ack(num)							;\
 	sti								;\
 	jmp	_C_LABEL(Xdoreti)	/* lower spl and do ASTs */	;\
 7:									\
-	UNLOCK_KERNEL							;\
 	cli								;\
 	orl     $(1 << num),CPUVAR(IPENDING)				;\
 	level_mask(num)							;\
Index: arch/x86/include/intrdefs.h
===================================================================
--- arch/x86/include/intrdefs.h	(revision 182)
+++ arch/x86/include/intrdefs.h	(working copy)
@@ -3,6 +3,9 @@
 #ifndef _i386_INTRDEFS_H
 #define _i386_INTRDEFS_H
 
+#ifdef _KERNEL_OPT
+#include "opt_multiprocessor.h"
+#endif /* _KERNEL_OPT */
 /*
  * Interrupt priority levels.
  * 
@@ -23,12 +26,22 @@
 #define	IPL_NONE	0x0	/* nothing */
 #define	IPL_SOFTCLOCK	0x4	/* timeouts */
 #define	IPL_SOFTNET	0x5	/* protocol stacks */
+#ifndef MULTIPROCESSOR
 #define	IPL_BIO		0x6	/* block I/O */
 #define	IPL_NET		0x7	/* network */
 #define	IPL_SOFTSERIAL	0x8	/* serial */
 #define	IPL_TTY		0x9	/* terminal */
 #define	IPL_VM		0xa	/* memory allocation */
 #define	IPL_AUDIO	0xb	/* audio */
+#else /* MULTIPROCESSOR */
+/* XXX XXX for locking order */
+#define	IPL_BIO		0x7	/* block I/O */
+#define	IPL_NET		0x7	/* network */
+#define	IPL_SOFTSERIAL	0x7	/* serial */
+#define	IPL_TTY		0x7	/* terminal */
+#define	IPL_VM		0x7	/* memory allocation */
+#define	IPL_AUDIO	0x7	/* audio */
+#endif /* MULTIPROCESSOR */
 #define	IPL_CLOCK	0xc	/* clock */
 #define IPL_SCHED	IPL_CLOCK
 #define	IPL_HIGH	0xd	/* everything */
@@ -36,6 +49,9 @@
 #define IPL_IPI		0xe	/* inter-processor interrupts */
 #define	NIPL		16
 
+#define	IH_FLAG_MPSAFE	0x80000000
+#define	IPL_FLAGS_MASK	(IH_FLAG_MPSAFE)
+
 /* Interrupt sharing types. */
 #define	IST_NONE	0	/* none */
 #define	IST_PULSE	1	/* pulsed */
Index: arch/x86/include/intr.h
===================================================================
--- arch/x86/include/intr.h	(revision 422)
+++ arch/x86/include/intr.h	(working copy)
@@ -102,6 +102,9 @@ struct intrhand {
 	int	(*ih_fun)(void *);
 	void	*ih_arg;
 	int	ih_level;
+	int	ih_flags;
+	int	(*ih_realfun)(void *);
+	void	*ih_realarg;
 	struct	intrhand *ih_next;
 	int	ih_pin;
 	int	ih_slot;
Index: arch/x86/x86/intr.c
===================================================================
--- arch/x86/x86/intr.c	(revision 425)
+++ arch/x86/x86/intr.c	(working copy)
@@ -449,6 +449,25 @@ found:
 	return 0;
 }
 
+#ifdef MULTIPROCESSOR
+static int intr_biglock_wrapper(void *);
+
+static int
+intr_biglock_wrapper(void *vp)
+{
+	struct intrhand *ih = vp;
+	int ret;
+
+	KERNEL_LOCK(LK_EXCLUSIVE|LK_CANRECURSE);
+
+	ret = (*ih->ih_realfun)(ih->ih_realarg);
+
+	KERNEL_UNLOCK();
+
+	return ret;
+}
+#endif /* MULTIPROCESSOR */
+
 void *
 intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level,
 	       int (*handler)(void *), void *arg)
@@ -458,6 +477,13 @@ intr_establish(int legacy_irq, struct pi
 	int slot, error, idt_vec;
 	struct intrsource *source;
 	struct intrstub *stubp;
+	int flags;
+
+	flags = level & IPL_FLAGS_MASK;		/* XXX */
+	level = level & ~IPL_FLAGS_MASK;	/* XXX */
+
+	if (level >= IPL_SCHED)			/* XXX */
+		flags |= IH_FLAG_MPSAFE;	/* XXX */
 
 #ifdef DIAGNOSTIC
 	if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15))
@@ -535,13 +561,19 @@ intr_establish(int legacy_irq, struct pi
 	     p = &q->ih_next)
 		;
 
-	ih->ih_fun = handler;
-	ih->ih_arg = arg;
+	ih->ih_fun = ih->ih_realfun = handler;
+	ih->ih_arg = ih->ih_realarg = arg;
 	ih->ih_next = *p;
 	ih->ih_level = level;
 	ih->ih_pin = pin;
 	ih->ih_cpu = ci;
 	ih->ih_slot = slot;
+#ifdef MULTIPROCESSOR
+	if ((flags & IH_FLAG_MPSAFE) == 0) {
+		ih->ih_fun = intr_biglock_wrapper;
+		ih->ih_arg = ih;
+	}
+#endif /* MULTIPROCESSOR */
 	*p = ih;
 
 	intr_calculatemasks(ci);
@@ -771,20 +803,6 @@ cpu_intr_init(struct cpu_info *ci)
 
 #ifdef MULTIPROCESSOR
 void
-x86_intlock(struct intrframe *iframe)
-{
-	if (iframe->if_ppl < IPL_SCHED)
-		spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
-}
-
-void
-x86_intunlock(struct intrframe *iframe)
-{
-	if (iframe->if_ppl < IPL_SCHED)
-		spinlockmgr(&kernel_lock, LK_RELEASE, 0);
-}
-
-void
 x86_softintlock(void)
 {
 	spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
Index: dev/pci/if_fxp_pci.c
===================================================================
--- dev/pci/if_fxp_pci.c	(revision 323)
+++ dev/pci/if_fxp_pci.c	(working copy)
@@ -477,7 +477,8 @@ fxp_pci_attach(parent, self, aux)
 		return;
 	}
 	intrstr = pci_intr_string(pc, ih);
-	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, fxp_intr, sc);
+	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET | IH_FLAG_MPSAFE,
+	    fxp_intr, sc);
 	if (sc->sc_ih == NULL) {
 		aprint_error("%s: couldn't establish interrupt",
 		    sc->sc_dev.dv_xname);
Index: dev/ic/i82557.c
===================================================================
--- dev/ic/i82557.c	(revision 455)
+++ dev/ic/i82557.c	(working copy)
@@ -182,10 +182,13 @@ int	fxp_80c24_mediachange(struct ifnet *
 void	fxp_80c24_mediastatus(struct ifnet *, struct ifmediareq *);
 
 void	fxp_start(struct ifnet *);
+void	fxp_start_body(struct ifnet *);
 int	fxp_ioctl(struct ifnet *, u_long, caddr_t);
 void	fxp_watchdog(struct ifnet *);
 int	fxp_init(struct ifnet *);
+int	fxp_init_body(struct ifnet *);
 void	fxp_stop(struct ifnet *, int);
+void	fxp_stop_body(struct ifnet *, int);
 
 void	fxp_txintr(struct fxp_softc *);
 void	fxp_rxintr(struct fxp_softc *);
@@ -209,6 +212,11 @@ void	fxp_load_ucode(struct fxp_softc *);
 void	fxp_shutdown(void *);
 void	fxp_power(int, void *);
 
+#define	FXP_LOCK_INIT(sc)	simple_lock_init(&(sc)->sc_slock)
+#define	FXP_LOCK(sc)		simple_lock(&(sc)->sc_slock)
+#define	FXP_UNLOCK(sc)		simple_unlock(&(sc)->sc_slock)
+#define	FXP_LOCK_HELD(sc)	simple_lock_held(&(sc)->sc_slock)
+
 int	fxp_copy_small = 0;
 
 /*
@@ -269,6 +277,7 @@ fxp_attach(struct fxp_softc *sc)
 	int rseg, i, error;
 	struct fxp_phytype *fp;
 
+	FXP_LOCK_INIT(sc);
 	callout_init(&sc->sc_callout);
 
 	/*
@@ -854,12 +863,28 @@ void
 fxp_start(struct ifnet *ifp)
 {
 	struct fxp_softc *sc = ifp->if_softc;
+
+	/* XXXMP */
+	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
+		return;
+
+	FXP_LOCK(sc);
+	fxp_start_body(ifp);
+	FXP_UNLOCK(sc);
+}
+
+void
+fxp_start_body(struct ifnet *ifp)
+{
+	struct fxp_softc *sc = ifp->if_softc;
 	struct mbuf *m0, *m;
 	struct fxp_txdesc *txd;
 	struct fxp_txsoft *txs;
 	bus_dmamap_t dmamap;
 	int error, lasttx, nexttx, opending, seg;
 
+	LOCK_ASSERT(FXP_LOCK_HELD(sc));
+
 	/*
 	 * If we want a re-init, bail out now.
 	 */
@@ -889,9 +914,12 @@ fxp_start(struct ifnet *ifp)
 		/*
 		 * Grab a packet off the queue.
 		 */
+		IFQ_LOCK(&ifp->if_snd);
 		IFQ_POLL(&ifp->if_snd, m0);
-		if (m0 == NULL)
+		if (m0 == NULL) {
+			IFQ_UNLOCK(&ifp->if_snd);
 			break;
+		}
 		m = NULL;
 
 		if (sc->sc_txpending == FXP_NTXCB) {
@@ -917,6 +945,7 @@ fxp_start(struct ifnet *ifp)
 		    BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
 			MGETHDR(m, M_DONTWAIT, MT_DATA);
 			if (m == NULL) {
+				IFQ_UNLOCK(&ifp->if_snd);
 				printf("%s: unable to allocate Tx mbuf\n",
 				    sc->sc_dev.dv_xname);
 				break;
@@ -925,6 +954,7 @@ fxp_start(struct ifnet *ifp)
 			if (m0->m_pkthdr.len > MHLEN) {
 				MCLGET(m, M_DONTWAIT);
 				if ((m->m_flags & M_EXT) == 0) {
+					IFQ_UNLOCK(&ifp->if_snd);
 					printf("%s: unable to allocate Tx "
 					    "cluster\n", sc->sc_dev.dv_xname);
 					m_freem(m);
@@ -936,6 +966,7 @@ fxp_start(struct ifnet *ifp)
 			error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
 			    m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
 			if (error) {
+				IFQ_UNLOCK(&ifp->if_snd);
 				printf("%s: unable to load Tx buffer, "
 				    "error = %d\n", sc->sc_dev.dv_xname, error);
 				break;
@@ -943,6 +974,7 @@ fxp_start(struct ifnet *ifp)
 		}
 
 		IFQ_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_UNLOCK(&ifp->if_snd);
 		csum_flags = m0->m_pkthdr.csum_flags;
 		if (m != NULL) {
 			m_freem(m0);
@@ -1077,6 +1109,8 @@ fxp_start(struct ifnet *ifp)
 	}
 }
 
+int fxp_bkl;
+int fxp_nobkl;
 /*
  * Process interface interrupts.
  */
@@ -1089,8 +1123,19 @@ fxp_intr(void *arg)
 	int claimed = 0;
 	u_int8_t statack;
 
-	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || sc->sc_enabled == 0)
+#ifdef MULTIPROCESSOR
+	if (kernel_lock.lk_cpu != cpu_number())
+		fxp_bkl++;
+	else
+		fxp_nobkl++;
+#endif
+
+	FXP_LOCK(sc);
+
+	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || sc->sc_enabled == 0) {
+		FXP_UNLOCK(sc);
 		return (0);
+	}
 	/*
 	 * If the interface isn't running, don't try to
 	 * service the interrupt.. just ack it and bail.
@@ -1101,6 +1146,7 @@ fxp_intr(void *arg)
 			claimed = 1;
 			CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);
 		}
+		FXP_UNLOCK(sc);
 		return (claimed);
 	}
 
@@ -1141,18 +1187,20 @@ fxp_intr(void *arg)
 			/*
 			 * Try to get more packets going.
 			 */
-			fxp_start(ifp);
+			fxp_start_body(ifp);
 
 			if (sc->sc_txpending == 0) {
 				/*
 				 * If we want a re-init, do that now.
 				 */
-				if (sc->sc_flags & FXPF_WANTINIT)
-					(void) fxp_init(ifp);
+				if (sc->sc_flags & FXPF_WANTINIT) {
+					(void) fxp_init_body(ifp);
+				}
 			}
 		}
 	}
 
+	FXP_UNLOCK(sc);
 #if NRND > 0
 	if (claimed)
 		rnd_add_uint32(&sc->rnd_source, statack);
@@ -1375,6 +1423,7 @@ fxp_tick(void *arg)
 		return;
 
 	s = splnet();
+	FXP_LOCK(sc);
 
 	FXP_CDSTATSSYNC(sc, BUS_DMASYNC_POSTREAD);
 
@@ -1413,7 +1462,8 @@ fxp_tick(void *arg)
 	 * speed transition).
 	 */
 	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
-		(void) fxp_init(ifp);
+		(void) fxp_init_body(ifp);
+		FXP_UNLOCK(sc);
 		splx(s);
 		return;
 	}
@@ -1450,6 +1500,7 @@ fxp_tick(void *arg)
 		mii_tick(&sc->sc_mii);
 	}
 
+	FXP_UNLOCK(sc);
 	splx(s);
 
 	/*
@@ -1486,6 +1537,16 @@ void
 fxp_stop(struct ifnet *ifp, int disable)
 {
 	struct fxp_softc *sc = ifp->if_softc;
+
+	FXP_LOCK(sc);
+	fxp_stop_body(ifp, disable);
+	FXP_UNLOCK(sc);
+}
+
+void
+fxp_stop_body(struct ifnet *ifp, int disable)
+{
+	struct fxp_softc *sc = ifp->if_softc;
 	struct fxp_txsoft *txs;
 	int i;
 
@@ -1530,7 +1591,6 @@ fxp_stop(struct ifnet *ifp, int disable)
 		fxp_rxdrain(sc);
 		fxp_disable(sc);
 	}
-
 }
 
 /*
@@ -1545,7 +1605,7 @@ fxp_watchdog(struct ifnet *ifp)
 	struct fxp_softc *sc = ifp->if_softc;
 
 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
-	ifp->if_oerrors++;
+	ifp->if_oerrors++; /* XXX MP */
 
 	(void) fxp_init(ifp);
 }
@@ -1557,6 +1617,19 @@ int
 fxp_init(struct ifnet *ifp)
 {
 	struct fxp_softc *sc = ifp->if_softc;
+	int ret;
+
+	FXP_LOCK(sc);
+	ret = fxp_init_body(ifp);
+	FXP_UNLOCK(sc);
+
+	return ret;
+}
+
+int
+fxp_init_body(struct ifnet *ifp)
+{
+	struct fxp_softc *sc = ifp->if_softc;
 	struct fxp_cb_config *cbp;
 	struct fxp_cb_ias *cb_ias;
 	struct fxp_txdesc *txd;
@@ -1569,7 +1642,7 @@ fxp_init(struct ifnet *ifp)
 	/*
 	 * Cancel any pending I/O
 	 */
-	fxp_stop(ifp, 0);
+	fxp_stop_body(ifp, 0);
 
 	/*
 	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
@@ -1868,7 +1941,7 @@ fxp_init(struct ifnet *ifp)
 	/*
 	 * Attempt to start output on the interface.
 	 */
-	fxp_start(ifp);
+	fxp_start_body(ifp);
 
  out:
 	if (error) {
@@ -2028,6 +2101,7 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
 	int s, error;
 
 	s = splnet();
+	FXP_LOCK(sc);
 
 	switch (cmd) {
 	case SIOCSIFMEDIA:
@@ -2036,7 +2110,9 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
 		break;
 
 	default:
+		FXP_UNLOCK(sc); /* XXXyamt */
 		error = ether_ioctl(ifp, cmd, data);
+		FXP_LOCK(sc);	/* XXXyamt */
 		if (error == ENETRESET) {
 			if (sc->sc_enabled) {
 				/*
@@ -2047,7 +2123,7 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
 					sc->sc_flags |= FXPF_WANTINIT;
 					error = 0;
 				} else
-					error = fxp_init(ifp);
+					error = fxp_init_body(ifp);
 			} else
 				error = 0;
 		}
@@ -2056,8 +2132,9 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
 
 	/* Try to get more packets going. */
 	if (sc->sc_enabled)
-		fxp_start(ifp);
+		fxp_start_body(ifp);
 
+	FXP_UNLOCK(sc);
 	splx(s);
 	return (error);
 }
Index: dev/ic/i82557var.h
===================================================================
--- dev/ic/i82557var.h	(revision 168)
+++ dev/ic/i82557var.h	(working copy)
@@ -165,6 +165,8 @@ struct fxp_txsoft {
  */
 struct fxp_softc {
 	struct device sc_dev;		/* generic device structures */
+	struct simplelock sc_slock;
+	struct simplelock sc_tx_slock;
 	bus_space_tag_t sc_st;		/* bus space tag */
 	bus_space_handle_t sc_sh;	/* bus space handle */
 	bus_dma_tag_t sc_dmat;		/* bus dma tag */
Index: net/if.c
===================================================================
--- net/if.c	(revision 462)
+++ net/if.c	(working copy)
@@ -435,6 +435,8 @@ if_attach(ifp)
 
 	ifindex2ifnet[ifp->if_index] = ifp;
 
+	IFQ_INIT(&ifp->if_snd);
+
 	/*
 	 * Link level name is allocated later by a separate call to
 	 * if_alloc_sadl().
Index: net/if.h
===================================================================
--- net/if.h	(revision 462)
+++ net/if.h	(working copy)
@@ -82,6 +82,7 @@
 
 #include <sys/socket.h>
 #include <sys/queue.h>
+#include <sys/lock.h>
 #include <net/dlt.h>
 #include <net/pfil.h>
 
@@ -223,6 +224,7 @@ struct if_data14 {
  * Structure defining a queue for a network interface.
  */
 struct ifqueue {
+	struct	simplelock ifq_slock;
 	struct	mbuf *ifq_head;
 	struct	mbuf *ifq_tail;
 	int	ifq_len;
@@ -230,6 +232,9 @@ struct ifqueue {
 	int	ifq_drops;
 };
 
+#define	IFQ_INITIALIZER(maxlen)	\
+	{SIMPLELOCK_INITIALIZER, NULL, NULL, 0, (maxlen), 0}
+
 /*
  * Structure defining a queue for a network interface.
  *
@@ -628,6 +633,19 @@ do {									\
 #endif /* DIAGNOSTIC */
 #endif /* IFAREF_DEBUG */
 
+#define	IFQ_LOCK_INIT(ifq)	simple_lock_init(&(ifq)->ifq_slock)
+#define	IFQ_LOCK(ifq)	simple_lock(&(ifq)->ifq_slock)
+#define	IFQ_UNLOCK(ifq)	simple_unlock(&(ifq)->ifq_slock)
+
+#define	IFQ_INIT(ifq)	\
+do {	\
+	IFQ_LOCK_INIT(ifq);	\
+	(ifq)->ifq_head = NULL;	\
+	(ifq)->ifq_tail = NULL;	\
+	(ifq)->ifq_len = 0;	\
+	(ifq)->ifq_drops = 0;	\
+} while (/*CONSTCOND*/ 0)
+
 #ifdef ALTQ
 #define	ALTQ_DECL(x)		x
 
Index: net/if_pppoe.c
===================================================================
--- net/if_pppoe.c	(revision 444)
+++ net/if_pppoe.c	(working copy)
@@ -147,8 +147,8 @@ struct pppoe_softc {
 };
 
 /* incoming traffic will be queued here */
-struct ifqueue ppoediscinq = { NULL };
-struct ifqueue ppoeinq = { NULL };
+struct ifqueue ppoediscinq;
+struct ifqueue ppoeinq;
 
 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
 void * pppoe_softintr = NULL;
@@ -212,7 +212,9 @@ pppoeattach(count)
 	LIST_INIT(&pppoe_softc_list);
 	if_clone_attach(&pppoe_cloner);
 
+	IFQ_INIT(&ppoediscinq);
 	ppoediscinq.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_INIT(&ppoeinq);
 	ppoeinq.ifq_maxlen = IFQ_MAXLEN;
 
 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
Index: net/if_ethersubr.c
===================================================================
--- net/if_ethersubr.c	(revision 390)
+++ net/if_ethersubr.c	(working copy)
@@ -536,7 +536,9 @@ ether_output(struct ifnet *ifp, struct m
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
+	IFQ_LOCK(&ifp->if_snd);
 	IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+	IFQ_UNLOCK(&ifp->if_snd);
 	if (error) {
 		/* mbuf is already freed */
 		splx(s);
@@ -814,11 +816,13 @@ ether_input(struct ifnet *ifp, struct mb
 		else
 			inq = &ppoeinq;
 		s = splnet();
+		IFQ_LOCK(inq);
 		if (IF_QFULL(inq)) {
 			IF_DROP(inq);
 			m_freem(m);
 		} else
 			IF_ENQUEUE(inq, m);
+		IFQ_UNLOCK(inq);
 		splx(s);
 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
 		if (!callout_pending(&pppoe_softintr))
@@ -1034,11 +1038,13 @@ ether_input(struct ifnet *ifp, struct mb
 	}
 
 	s = splnet();
+	IFQ_LOCK(inq);
 	if (IF_QFULL(inq)) {
 		IF_DROP(inq);
 		m_freem(m);
 	} else
 		IF_ENQUEUE(inq, m);
+	IFQ_UNLOCK(inq);
 	splx(s);
 }
 
Index: netinet6/ip6_input.c
===================================================================
--- netinet6/ip6_input.c	(revision 455)
+++ netinet6/ip6_input.c	(working copy)
@@ -167,6 +167,7 @@ ip6_init()
 		if (pr->pr_domain->dom_family == PF_INET6 &&
 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
 			ip6_protox[pr->pr_protocol] = pr - inet6sw;
+	IFQ_INIT(&ip6intrq);
 	ip6intrq.ifq_maxlen = ip6qmaxlen;
 	nd6_init();
 	frag6_init();
@@ -205,7 +206,9 @@ ip6intr()
 
 	for (;;) {
 		s = splnet();
+		IFQ_LOCK(&ip6intrq);
 		IF_DEQUEUE(&ip6intrq, m);
+		IFQ_UNLOCK(&ip6intrq);
 		splx(s);
 		if (m == 0)
 			return;

--NextPart-20031230132714-0843500--