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