Date: Fri, 8 Oct 2010 21:54:33 +0000 (UTC) From: Weongyo Jeong <weongyo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r213633 - user/weongyo/usb/sys/dev/usb/net Message-ID: <201010082154.o98LsXlA015481@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010082154.o98LsXlA015481>