svn commit: r213633 - user/weongyo/usb/sys/dev/usb/net

Weongyo Jeong weongyo at FreeBSD.org
Fri Oct 8 21:54:34 UTC 2010


Author: weongyo
Date: Fri Oct  8 21:54:33 2010
New Revision: 213633
URL: http://svn.freebsd.org/changeset/base/213633

Log:
  Fixes a regression that device up and down wasn't synchronous.  To make
  it synchronous sx(9) is used only for up / down cases though in the
  previous the taskqueue was used.

Modified:
  user/weongyo/usb/sys/dev/usb/net/if_aue.c
  user/weongyo/usb/sys/dev/usb/net/if_auereg.h
  user/weongyo/usb/sys/dev/usb/net/if_axe.c
  user/weongyo/usb/sys/dev/usb/net/if_axereg.h
  user/weongyo/usb/sys/dev/usb/net/if_cdce.c
  user/weongyo/usb/sys/dev/usb/net/if_cdcereg.h
  user/weongyo/usb/sys/dev/usb/net/if_cue.c
  user/weongyo/usb/sys/dev/usb/net/if_cuereg.h
  user/weongyo/usb/sys/dev/usb/net/if_kue.c
  user/weongyo/usb/sys/dev/usb/net/if_kuereg.h
  user/weongyo/usb/sys/dev/usb/net/if_rue.c
  user/weongyo/usb/sys/dev/usb/net/if_ruereg.h
  user/weongyo/usb/sys/dev/usb/net/if_udav.c
  user/weongyo/usb/sys/dev/usb/net/if_udavreg.h
  user/weongyo/usb/sys/dev/usb/net/uhso.c

Modified: user/weongyo/usb/sys/dev/usb/net/if_aue.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_aue.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_aue.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -225,6 +225,7 @@ static int	aue_ioctl(struct ifnet *, u_l
 static void	aue_start(struct ifnet *);
 static void	aue_start_locked(struct ifnet *);
 static void	aue_init(void *);
+static void	aue_stop_locked(struct aue_softc *);
 static void	aue_setmulti(void *, int);
 static void	aue_setmulti_locked(struct aue_softc *);
 static void	aue_rxflush(struct aue_softc *);
@@ -707,6 +708,7 @@ aue_attach(device_t dev)
 	sc->sc_udev = uaa->device;
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "aue sxlock");
 	sleepout_create(&sc->sc_sleepout, "aue sleepout");
 	sleepout_init_mtx(&sc->sc_sleepout, &sc->sc_watchdog, &sc->sc_mtx, 0);
 	TASK_INIT(&sc->sc_setmulti, 0, aue_setmulti, sc);
@@ -780,6 +782,7 @@ aue_detach(device_t dev)
 		if_free(ifp);
 	}
 	sleepout_free(&sc->sc_sleepout);
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -1012,9 +1015,11 @@ aue_init(void *arg)
 {
 	struct aue_softc *sc = arg;
 
+	AUE_SXLOCK(sc);
 	AUE_LOCK(sc);
 	aue_init_locked(sc);
 	AUE_UNLOCK(sc);
+	AUE_SXUNLOCK(sc);
 }
 
 static void
@@ -1121,6 +1126,17 @@ aue_ifmedia_sts(struct ifnet *ifp, struc
 static void
 aue_stop(struct aue_softc *sc)
 {
+
+	AUE_SXLOCK(sc);
+	AUE_LOCK(sc);
+	aue_stop_locked(sc);
+	AUE_UNLOCK(sc);
+	AUE_SXUNLOCK(sc);
+}
+
+static void
+aue_stop_locked(struct aue_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	AUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -1146,20 +1162,24 @@ aue_ioctl(struct ifnet *ifp, u_long comm
 	struct aue_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct mii_data *mii = GET_MII(sc);
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		AUE_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		AUE_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if (drv_flags & IFF_DRV_RUNNING)
 				SLEEPOUT_RUNTASK(&sc->sc_sleepout,
 				    &sc->sc_setpromisc);
 			else
-				aue_init_locked(sc);
+				aue_init(sc);
 		} else
 			aue_stop(sc);
-		AUE_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: user/weongyo/usb/sys/dev/usb/net/if_auereg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_auereg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_auereg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -208,6 +208,7 @@ struct aue_softc {
 	struct usb_device	*sc_udev; /* used by uether_do_request() */
 	struct usb_xfer		*sc_xfer[AUE_N_TRANSFER];
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	struct ifqueue		sc_rxq;
 	/* ethernet address from eeprom */
 	uint8_t			sc_eaddr[ETHER_ADDR_LEN];
@@ -225,6 +226,8 @@ struct aue_softc {
 	struct task		sc_setpromisc;
 };
 
+#define	AUE_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	AUE_SXUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
 #define	AUE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	AUE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	AUE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/if_axe.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_axe.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_axe.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -205,6 +205,7 @@ static void	axe_start(struct ifnet *);
 static void	axe_start_locked(struct ifnet *);
 static void	axe_tick(struct axe_softc *);
 static void	axe_stop(struct axe_softc *);
+static void	axe_stop_locked(struct axe_softc *);
 static void	axe_setmulti_locked(struct axe_softc *);
 static void	axe_setpromisc(void *, int);
 static void	axe_setpromisc_locked(struct axe_softc *);
@@ -786,6 +787,7 @@ axe_attach(device_t dev)
 	sc->sc_udev = uaa->device;
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "axe sxlock");
 	sleepout_create(&sc->sc_sleepout, "axe sleepout");
 	sleepout_init_mtx(&sc->sc_sleepout, &sc->sc_watchdog, &sc->sc_mtx, 0);
 	TASK_INIT(&sc->sc_setmulti, 0, axe_setmulti, sc);
@@ -863,6 +865,7 @@ axe_detach(device_t dev)
 		if_free(ifp);
 	}
 	sleepout_free(&sc->sc_sleepout);
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -1169,9 +1172,11 @@ axe_init(void *arg)
 {
 	struct axe_softc *sc = arg;
 
+	AXE_SXLOCK(sc);
 	AXE_LOCK(sc);
 	axe_init_locked(sc);
 	AXE_UNLOCK(sc);
+	AXE_SXUNLOCK(sc);
 }
 
 static void
@@ -1183,7 +1188,7 @@ axe_init_locked(struct axe_softc *sc)
 	AXE_LOCK_ASSERT(sc, MA_OWNED);
 
 	/* Cancel pending I/O */
-	axe_stop(sc);
+	axe_stop_locked(sc);
 
 	/* Set MAC address. */
 	if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772))
@@ -1268,6 +1273,17 @@ axe_setpromisc_locked(struct axe_softc *
 static void
 axe_stop(struct axe_softc *sc)
 {
+
+	AXE_SXLOCK(sc);
+	AXE_LOCK(sc);
+	axe_stop_locked(sc);
+	AXE_UNLOCK(sc);
+	AXE_SXUNLOCK(sc);
+}
+
+static void
+axe_stop_locked(struct axe_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	AXE_LOCK_ASSERT(sc, MA_OWNED);
@@ -1293,20 +1309,24 @@ axe_ioctl(struct ifnet *ifp, u_long comm
 	struct axe_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct mii_data *mii = GET_MII(sc);
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		AXE_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		AXE_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if (drv_flags & IFF_DRV_RUNNING)
 				SLEEPOUT_RUNTASK(&sc->sc_sleepout,
 				    &sc->sc_setpromisc);
 			else
-				axe_init_locked(sc);
+				axe_init(sc);
 		} else
 			axe_stop(sc);
-		AXE_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: user/weongyo/usb/sys/dev/usb/net/if_axereg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_axereg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_axereg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -201,6 +201,7 @@ struct axe_softc {
 	device_t		sc_miibus;
 	struct usb_device	*sc_udev; /* used by uether_do_request() */
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	struct usb_xfer		*sc_xfer[AXE_N_TRANSFER];
 
 	/* ethernet address from eeprom */
@@ -221,6 +222,8 @@ struct axe_softc {
 	uint8_t			sc_phyaddrs[2];
 };
 
+#define	AXE_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	AXE_SXUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
 #define	AXE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	AXE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	AXE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/if_cdce.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_cdce.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_cdce.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -111,6 +111,7 @@ static void	cdce_start(struct ifnet *);
 static void	cdce_start_locked(struct ifnet *);
 static void	cdce_init(void *);
 static void	cdce_init_locked(struct cdce_softc *);
+static void	cdce_stop_locked(struct cdce_softc *);
 static int	cdce_rxmbuf(struct cdce_softc *, struct mbuf *, unsigned int);
 static struct mbuf *cdce_newbuf(void);
 static void	cdce_rxflush(struct cdce_softc *);
@@ -446,6 +447,7 @@ cdce_attach(device_t dev)
 	sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "cdce sxlock");
 
 	ud = usbd_find_descriptor
 	    (uaa->device, NULL, uaa->info.bIfaceIndex,
@@ -615,6 +617,7 @@ cdce_detach(device_t dev)
 		ether_ifdetach(ifp);
 		if_free(ifp);
 	}
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 	return (0);
 }
@@ -773,9 +776,11 @@ cdce_init(void *arg)
 {
 	struct cdce_softc *sc = arg;
 
+	CDCE_SXLOCK(sc);
 	CDCE_LOCK(sc);
 	cdce_init_locked(sc);
 	CDCE_UNLOCK(sc);
+	CDCE_SXUNLOCK(sc);
 }
 
 static void
@@ -801,6 +806,17 @@ cdce_init_locked(struct cdce_softc *sc)
 static void
 cdce_stop(struct cdce_softc *sc)
 {
+
+	CDCE_SXLOCK(sc);
+	CDCE_LOCK(sc);
+	cdce_stop_locked(sc);
+	CDCE_UNLOCK(sc);
+	CDCE_SXUNLOCK(sc);
+}
+
+static void
+cdce_stop_locked(struct cdce_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	CDCE_LOCK_ASSERT(sc, MA_OWNED);
@@ -1333,17 +1349,21 @@ static int
 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct cdce_softc *sc = ifp->if_softc;
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		CDCE_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-				cdce_init_locked(sc);
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		CDCE_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if ((drv_flags & IFF_DRV_RUNNING) == 0)
+				cdce_init(sc);
 		} else
 			cdce_stop(sc);
-		CDCE_UNLOCK(sc);
 		break;
 	default:
 		error = ether_ioctl(ifp, command, data);

Modified: user/weongyo/usb/sys/dev/usb/net/if_cdcereg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_cdcereg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_cdcereg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -75,6 +75,7 @@ struct cdce_softc {
 	device_t		sc_dev;
 	struct usb_device	*sc_udev; /* used by uether_do_request() */
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	struct usb_xfer		*sc_xfer[CDCE_N_TRANSFER];
 	struct ifqueue		sc_rxq;
 	/* ethernet address from eeprom */
@@ -92,6 +93,8 @@ struct cdce_softc {
 	uint8_t			sc_ifaces_index[2];
 };
 
+#define	CDCE_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	CDCE_SXUNLOCK(_sc)		sx_xunlock(&(_sc)->sc_sx)
 #define	CDCE_LOCK(_sc)			mtx_lock(&(_sc)->sc_mtx)
 #define	CDCE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	CDCE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/if_cue.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_cue.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_cue.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -130,6 +130,7 @@ static int	cue_rxbuf(struct cue_softc *,
 		    unsigned int, unsigned int);
 static void	cue_rxflush(struct cue_softc *);
 static void	cue_stop(struct cue_softc *);
+static void	cue_stop_locked(struct cue_softc *);
 static void	cue_watchdog(void *);
 static void	cue_setpromisc(void *, int);
 static void	cue_setpromisc_locked(struct cue_softc *);
@@ -416,6 +417,7 @@ cue_attach(device_t dev)
 	sc->sc_dev = dev;
 	sc->sc_udev = uaa->device;
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "cue sxlock");
 	sleepout_create(&sc->sc_sleepout, "cue sleepout");
 	sleepout_init_mtx(&sc->sc_sleepout, &sc->sc_watchdog, &sc->sc_mtx, 0);
 	TASK_INIT(&sc->sc_setpromisc, 0, cue_setpromisc, sc);
@@ -478,6 +480,7 @@ cue_detach(device_t dev)
 		if_free(ifp);
 	}
 	sleepout_free(&sc->sc_sleepout);
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -629,9 +632,11 @@ cue_init(void *arg)
 {
 	struct cue_softc *sc = arg;
 
+	CUE_SXLOCK(sc);
 	CUE_LOCK(sc);
 	cue_init_locked(sc);
 	CUE_UNLOCK(sc);
+	CUE_SXUNLOCK(sc);
 }
 
 static void
@@ -645,7 +650,7 @@ cue_init_locked(struct cue_softc *sc)
 	/*
 	 * Cancel pending I/O and free all RX/TX buffers.
 	 */
-	cue_stop(sc);
+	cue_stop_locked(sc);
 #if 0
 	cue_reset(sc);
 #endif
@@ -687,6 +692,17 @@ cue_init_locked(struct cue_softc *sc)
 static void
 cue_stop(struct cue_softc *sc)
 {
+
+	CUE_SXLOCK(sc);
+	CUE_LOCK(sc);
+	cue_stop_locked(sc);
+	CUE_UNLOCK(sc);
+	CUE_SXUNLOCK(sc);
+}
+
+static void
+cue_stop_locked(struct cue_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	CUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -773,20 +789,24 @@ static int
 cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct cue_softc *sc = ifp->if_softc;
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		CUE_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		CUE_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if (drv_flags & IFF_DRV_RUNNING)
 				SLEEPOUT_RUNTASK(&sc->sc_sleepout,
 				    &sc->sc_setpromisc);
 			else
-				cue_init_locked(sc);
+				cue_init(sc);
 		} else
 			cue_stop(sc);
-		CUE_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: user/weongyo/usb/sys/dev/usb/net/if_cuereg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_cuereg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_cuereg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -121,6 +121,7 @@ enum {
 struct cue_softc {
 	struct ifnet		*sc_ifp;
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	device_t		sc_dev;
 	struct usb_device	*sc_udev; /* used by uether_do_request() */
 	struct usb_xfer		*sc_xfer[CUE_N_TRANSFER];
@@ -135,6 +136,8 @@ struct cue_softc {
 #define	CUE_FLAG_LINK		0x0001	/* got a link */
 };
 
+#define	CUE_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	CUE_SXUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
 #define	CUE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	CUE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	CUE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/if_kue.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_kue.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_kue.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -166,6 +166,7 @@ static int	kue_load_fw(struct kue_softc 
 static void	kue_reset(struct kue_softc *);
 static void	kue_init(void *);
 static void	kue_init_locked(struct kue_softc *);
+static void	kue_stop_locked(struct kue_softc *);
 static int	kue_ioctl(struct ifnet *, u_long, caddr_t);
 static void	kue_start(struct ifnet *);
 static void	kue_start_locked(struct ifnet *);
@@ -472,6 +473,7 @@ kue_attach(device_t dev)
 	sc->sc_dev = dev;
 	sc->sc_udev = uaa->device;
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "kue sxlock");
 	sleepout_create(&sc->sc_sleepout, "kue sleepout");
 	TASK_INIT(&sc->sc_setmulti, 0, kue_setmulti, sc);
 
@@ -537,6 +539,7 @@ kue_detach(device_t dev)
 		if_free(ifp);
 	}
 	sleepout_free(&sc->sc_sleepout);
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 	free(sc->sc_mcfilters, M_USBDEV);
 
@@ -750,9 +753,11 @@ kue_init(void *arg)
 {
 	struct kue_softc *sc = arg;
 
+	KUE_SXLOCK(sc);
 	KUE_LOCK(sc);
 	kue_init_locked(sc);
 	KUE_UNLOCK(sc);
+	KUE_SXUNLOCK(sc);
 }
 
 static void
@@ -788,6 +793,17 @@ kue_init_locked(struct kue_softc *sc)
 static void
 kue_stop(struct kue_softc *sc)
 {
+
+	KUE_SXLOCK(sc);
+	KUE_LOCK(sc);
+	kue_stop_locked(sc);
+	KUE_UNLOCK(sc);
+	KUE_SXUNLOCK(sc);
+}
+
+static void
+kue_stop_locked(struct kue_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	KUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -805,17 +821,21 @@ static int
 kue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct kue_softc *sc = ifp->if_softc;
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		KUE_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-				kue_init_locked(sc);
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		KUE_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if ((drv_flags & IFF_DRV_RUNNING) == 0)
+				kue_init(sc);
 		} else
 			kue_stop(sc);
-		KUE_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: user/weongyo/usb/sys/dev/usb/net/if_kuereg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_kuereg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_kuereg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -129,6 +129,7 @@ struct kue_softc {
 	struct usb_device	*sc_udev; /* used by uether_do_request() */
 	struct usb_xfer		*sc_xfer[KUE_N_TRANSFER];
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	struct sleepout		sc_sleepout;
 	struct task		sc_setmulti;
 	struct ifqueue		sc_rxq;
@@ -141,6 +142,8 @@ struct kue_softc {
 	uint16_t		sc_rxfilt;
 };
 
+#define	KUE_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	KUE_SXUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
 #define	KUE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	KUE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	KUE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/if_rue.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_rue.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_rue.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -159,6 +159,7 @@ static int	rue_ioctl(struct ifnet *, u_l
 static void	rue_start(struct ifnet *);
 static void	rue_start_locked(struct ifnet *);
 static void	rue_stop(struct rue_softc *);
+static void	rue_stop_locked(struct rue_softc *);
 static void	rue_watchdog(void *);
 static void	rue_setpromisc(void *, int);
 static void	rue_setpromisc_locked(struct rue_softc *);
@@ -942,9 +943,11 @@ rue_init(void *arg)
 {
 	struct rue_softc *sc = arg;
 
+	RUE_SXLOCK(sc);
 	RUE_LOCK(sc);
 	rue_init_locked(sc);
 	RUE_UNLOCK(sc);
+	RUE_SXUNLOCK(sc);
 }
 
 static void
@@ -962,7 +965,7 @@ rue_init_locked(struct rue_softc *sc)
 	/* Set MAC address */
 	rue_write_mem(sc, RUE_IDR0, IF_LLADDR(ifp), ETHER_ADDR_LEN);
 
-	rue_stop(sc);
+	rue_stop_locked(sc);
 
 	/*
 	 * Set the initial TX and RX configuration.
@@ -1026,6 +1029,17 @@ rue_ifmedia_sts(struct ifnet *ifp, struc
 static void
 rue_stop(struct rue_softc *sc)
 {
+
+	RUE_SXLOCK(sc);
+	RUE_LOCK(sc);
+	rue_stop_locked(sc);
+	RUE_UNLOCK(sc);
+	RUE_SXUNLOCK(sc);
+}
+
+static void
+rue_stop_locked(struct rue_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	RUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -1051,20 +1065,24 @@ rue_ioctl(struct ifnet *ifp, u_long comm
 	struct rue_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct mii_data *mii = GET_MII(sc);
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		RUE_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		RUE_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if (drv_flags & IFF_DRV_RUNNING)
 				SLEEPOUT_RUNTASK(&sc->sc_sleepout,
 				    &sc->sc_setpromisc);
 			else
-				rue_init_locked(sc);
+				rue_init(sc);
 		} else
 			rue_stop(sc);
-		RUE_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: user/weongyo/usb/sys/dev/usb/net/if_ruereg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_ruereg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_ruereg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -174,6 +174,7 @@ struct rue_softc {
 	device_t		sc_dev;
 	device_t		sc_miibus;
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	struct usb_device	*sc_udev; /* used by uether_do_request() */
 	struct usb_xfer		*sc_xfer[RUE_N_TRANSFER];
 	struct sleepout		sc_sleepout;
@@ -187,6 +188,8 @@ struct rue_softc {
 #define	RUE_FLAG_LINK		0x0001
 };
 
+#define	RUE_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	RUE_SXUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
 #define	RUE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	RUE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	RUE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/if_udav.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_udav.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_udav.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -111,6 +111,7 @@ static int	udav_ifmedia_upd(struct ifnet
 static void	udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
 static void	udav_init(void *);
 static void	udav_init_locked(struct udav_softc *);
+static void	udav_stop_locked(struct udav_softc *);
 static int	udav_ioctl(struct ifnet *, u_long, caddr_t);
 static void	udav_start(struct ifnet *);
 static void	udav_start_locked(struct ifnet *);
@@ -248,6 +249,7 @@ udav_attach(device_t dev)
 	sc->sc_udev = uaa->device;
 	sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "udav sxlock");
 	sleepout_create(&sc->sc_sleepout, "axe sleepout");
 	sleepout_init_mtx(&sc->sc_sleepout, &sc->sc_watchdog, &sc->sc_mtx, 0);
 	TASK_INIT(&sc->sc_setmulti, 0, udav_setmulti, sc);
@@ -320,6 +322,7 @@ udav_detach(device_t dev)
 		if_free(ifp);
 	}
 	sleepout_free(&sc->sc_sleepout);
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -443,9 +446,11 @@ udav_init(void *arg)
 {
 	struct udav_softc *sc = arg;
 
+	UDAV_SXLOCK(sc);
 	UDAV_LOCK(sc);
 	udav_init_locked(sc);
 	UDAV_UNLOCK(sc);
+	UDAV_SXUNLOCK(sc);
 }
 
 static void
@@ -458,7 +463,7 @@ udav_init_locked(struct udav_softc *sc)
 	/*
 	 * Cancel pending I/O
 	 */
-	udav_stop(sc);
+	udav_stop_locked(sc);
 
 	/* set MAC address */
 	udav_csr_write(sc, UDAV_PAR, IF_LLADDR(ifp), ETHER_ADDR_LEN);
@@ -832,6 +837,17 @@ tr_setup:
 static void
 udav_stop(struct udav_softc *sc)
 {
+
+	UDAV_SXLOCK(sc);
+	UDAV_LOCK(sc);
+	udav_stop_locked(sc);
+	UDAV_UNLOCK(sc);
+	UDAV_SXUNLOCK(sc);
+}
+
+static void
+udav_stop_locked(struct udav_softc *sc)
+{
 	struct ifnet *ifp = sc->sc_ifp;
 
 	UDAV_LOCK_ASSERT(sc, MA_OWNED);
@@ -988,20 +1004,24 @@ udav_ioctl(struct ifnet *ifp, u_long com
 	struct udav_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct mii_data *mii = GET_MII(sc);
-	int error = 0;
+	int error = 0, drv_flags, flags;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
+		/* Avoids race and LOR between mutex and sx lock. */
 		UDAV_LOCK(sc);
-		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		UDAV_UNLOCK(sc);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if (drv_flags & IFF_DRV_RUNNING)
 				SLEEPOUT_RUNTASK(&sc->sc_sleepout,
 				    &sc->sc_setpromisc);
 			else
-				udav_init_locked(sc);
+				udav_init(sc);
 		} else
 			udav_stop(sc);
-		UDAV_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: user/weongyo/usb/sys/dev/usb/net/if_udavreg.h
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/if_udavreg.h	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/if_udavreg.h	Fri Oct  8 21:54:33 2010	(r213633)
@@ -158,6 +158,7 @@ struct udav_softc {
 	struct usb_device	*sc_udev;
 	struct usb_xfer		*sc_xfer[UDAV_N_TRANSFER];
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	struct sleepout		sc_sleepout;
 	struct sleepout_task	sc_watchdog;
 	struct task		sc_setmulti;
@@ -170,6 +171,8 @@ struct udav_softc {
 #define	UDAV_FLAG_EXT_PHY	0x0040
 };
 
+#define	UDAV_SXLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
+#define	UDAV_SXUNLOCK(_sc)		sx_xunlock(&(_sc)->sc_sx)
 #define	UDAV_LOCK(_sc)			mtx_lock(&(_sc)->sc_mtx)
 #define	UDAV_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	UDAV_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)

Modified: user/weongyo/usb/sys/dev/usb/net/uhso.c
==============================================================================
--- user/weongyo/usb/sys/dev/usb/net/uhso.c	Fri Oct  8 21:29:48 2010	(r213632)
+++ user/weongyo/usb/sys/dev/usb/net/uhso.c	Fri Oct  8 21:54:33 2010	(r213633)
@@ -78,6 +78,7 @@ struct uhso_softc {
 	device_t		sc_dev;
 	struct usb_device	*sc_udev;
 	struct mtx		sc_mtx;
+	struct sx		sc_sx;
 	uint32_t		sc_type;	/* Interface definition */
 	int			sc_radio;
 
@@ -106,6 +107,9 @@ struct uhso_softc {
 	int			sc_line;
 };
 
+#define	UHSO_SXLOCK(_sc)	sx_xlock(&(_sc)->sc_sx)
+#define	UHSO_SXUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
+
 #define UHSO_MAX_MTU		2048
 
 /*
@@ -461,6 +465,7 @@ static void uhso_ucom_cfg_set_rts(struct
 static void uhso_if_init(void *);
 static void uhso_if_start(struct ifnet *);
 static void uhso_if_stop(struct uhso_softc *);
+static void uhso_if_stop_locked(struct uhso_softc *);
 static int  uhso_if_ioctl(struct ifnet *, u_long, caddr_t);
 static int  uhso_if_output(struct ifnet *, struct mbuf *, struct sockaddr *,
     struct route *);
@@ -548,6 +553,7 @@ uhso_attach(device_t self)
 	sc->sc_dev = self;
 	sc->sc_udev = uaa->device;
 	mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
+	sx_init(&sc->sc_sx, "uhso sxlock");
 
 	sc->sc_ucom = NULL;
 	sc->sc_ttys = 0;
@@ -681,7 +687,7 @@ uhso_detach(device_t self)
 		callout_drain(&sc->sc_c);
 		free_unr(uhso_ifnet_unit, sc->sc_ifp->if_dunit);
 		mtx_lock(&sc->sc_mtx);
-		uhso_if_stop(sc);
+		uhso_if_stop_locked(sc);
 		bpfdetach(sc->sc_ifp);
 		if_detach(sc->sc_ifp);
 		if_free(sc->sc_ifp);
@@ -689,6 +695,7 @@ uhso_detach(device_t self)
 		usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
 	}
 
+	sx_destroy(&sc->sc_sx);
 	mtx_destroy(&sc->sc_mtx);
 	return (0);
 }
@@ -1801,21 +1808,25 @@ static int
 uhso_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
 	struct uhso_softc *sc;
+	int drv_flags, flags;
 
 	sc = ifp->if_softc;
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
-		if (ifp->if_flags & IFF_UP) {
-			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+		/* Avoids race and LOR between mutex and sx lock. */
+		mtx_lock(&sc->sc_mtx);
+		flags = ifp->if_flags;
+		drv_flags = ifp->if_drv_flags;
+		mtx_unlock(&sc->sc_mtx);
+		/* device up and down is synchronous using sx(9) lock */
+		if (flags & IFF_UP) {
+			if (!(drv_flags & IFF_DRV_RUNNING))
 				uhso_if_init(sc);
 		}
 		else {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-				mtx_lock(&sc->sc_mtx);
+			if (drv_flags & IFF_DRV_RUNNING)
 				uhso_if_stop(sc);
-				mtx_unlock(&sc->sc_mtx);
-			}
 		}
 		break;
 	case SIOCSIFADDR:
@@ -1835,12 +1846,14 @@ uhso_if_init(void *priv)
 	struct uhso_softc *sc = priv;
 	struct ifnet *ifp = sc->sc_ifp;
 
+	UHSO_SXLOCK(sc);
 	mtx_lock(&sc->sc_mtx);
-	uhso_if_stop(sc);
+	uhso_if_stop_locked(sc);
 	ifp = sc->sc_ifp;
 	ifp->if_flags |= IFF_UP;
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	mtx_unlock(&sc->sc_mtx);
+	UHSO_SXUNLOCK(sc);
 
 	UHSO_DPRINTF(2, "ifnet initialized\n");
 }
@@ -1889,6 +1902,17 @@ static void
 uhso_if_stop(struct uhso_softc *sc)
 {
 
+	UHSO_SXLOCK(sc);
+	mtx_lock(&sc->sc_mtx);
+	uhso_if_stop_locked(sc);
+	mtx_unlock(&sc->sc_mtx);
+	UHSO_SXUNLOCK(sc);
+}
+
+static void
+uhso_if_stop_locked(struct uhso_softc *sc)
+{
+
 	usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_READ]);
 	usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_WRITE]);
 	sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);


More information about the svn-src-user mailing list