diff --git a/sys/dev/usb/net/if_aue.c b/sys/dev/usb/net/if_aue.c index 84268c60a780..3378ba9f2a56 100644 --- a/sys/dev/usb/net/if_aue.c +++ b/sys/dev/usb/net/if_aue.c @@ -692,6 +840,7 @@ aue_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + sx_init(&sc->sc_mii_lock, "auemii"); iface_index = AUE_IFACE_IDX; error = usbd_transfer_setup(uaa->device, &iface_index, @@ -728,6 +877,7 @@ aue_detach(device_t dev) usbd_transfer_unsetup(sc->sc_xfer, AUE_N_TRANSFER); uether_ifdetach(ue); + sx_destroy(&sc->sc_mii_lock); mtx_destroy(&sc->sc_mtx); return (0); @@ -930,6 +1080,13 @@ aue_tick(struct usb_ether *ue) AUE_LOCK_ASSERT(sc, MA_OWNED); + AUE_UNLOCK(sc); + if (!AUE_MII_TRYLOCK(sc)) { + AUE_LOCK(sc); + return; + } + AUE_LOCK(sc); + mii_tick(mii); if ((sc->sc_flags & AUE_FLAG_LINK) == 0 && mii->mii_media_status & IFM_ACTIVE && @@ -937,6 +1094,9 @@ aue_tick(struct usb_ether *ue) sc->sc_flags |= AUE_FLAG_LINK; aue_start(ue); } + AUE_UNLOCK(sc); + AUE_MII_UNLOCK(sc); + AUE_LOCK(sc); } static void @@ -1015,10 +1175,19 @@ aue_ifmedia_upd(if_t ifp) AUE_LOCK_ASSERT(sc, MA_OWNED); + AUE_UNLOCK(sc); + AUE_MII_LOCK(sc); + AUE_LOCK(sc); + sc->sc_flags &= ~AUE_FLAG_LINK; LIST_FOREACH(miisc, &mii->mii_phys, mii_list) PHY_RESET(miisc); error = mii_mediachg(mii); + + AUE_UNLOCK(sc); + AUE_MII_UNLOCK(sc); + AUE_LOCK(sc); + return (error); } @@ -1031,11 +1200,13 @@ aue_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) struct aue_softc *sc = if_getsoftc(ifp); struct mii_data *mii = GET_MII(sc); + AUE_MII_LOCK(sc); AUE_LOCK(sc); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; AUE_UNLOCK(sc); + AUE_MII_UNLOCK(sc); } /* diff --git a/sys/dev/usb/net/if_auereg.h b/sys/dev/usb/net/if_auereg.h index 7f2d56dccdd5..bc1945626b73 100644 --- a/sys/dev/usb/net/if_auereg.h +++ b/sys/dev/usb/net/if_auereg.h @@ -204,8 +204,11 @@ struct aue_rxpkt { struct aue_softc { struct usb_ether sc_ue; struct mtx sc_mtx; + struct sx sc_mii_lock; struct usb_xfer *sc_xfer[AUE_N_TRANSFER]; + int sc_phyno; + int sc_flags; #define AUE_FLAG_LSYS 0x0001 /* use Linksys reset */ #define AUE_FLAG_PNA 0x0002 /* has Home PNA */ @@ -218,3 +221,6 @@ struct aue_softc { #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) +#define AUE_MII_LOCK(_sc) sx_xlock(&(_sc)->sc_mii_lock) +#define AUE_MII_UNLOCK(_sc) sx_xunlock(&(_sc)->sc_mii_lock) +#define AUE_MII_TRYLOCK(_sc) sx_try_xlock(&(_sc)->sc_mii_lock)