diff --git a/sys/dev/usb/net/if_axge.c b/sys/dev/usb/net/if_axge.c --- a/sys/dev/usb/net/if_axge.c +++ b/sys/dev/usb/net/if_axge.c @@ -507,10 +507,17 @@ mii = GET_MII(sc); AXGE_LOCK_ASSERT(sc, MA_OWNED); + AXGE_UNLOCK(sc); + AXGE_MII_LOCK(sc); + AXGE_LOCK(sc); + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) PHY_RESET(miisc); error = mii_mediachg(mii); + AXGE_UNLOCK(sc); + AXGE_MII_UNLOCK(sc); + AXGE_LOCK(sc); return (error); } @@ -525,11 +532,13 @@ sc = if_getsoftc(ifp); mii = GET_MII(sc); + AXGE_MII_LOCK(sc); AXGE_LOCK(sc); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; AXGE_UNLOCK(sc); + AXGE_MII_UNLOCK(sc); } /* @@ -570,6 +579,7 @@ device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + sx_init(&sc->sc_mii_lock, "axgemii"); sc->sc_flags = USB_GET_DRIVER_INFO(uaa); @@ -631,6 +641,7 @@ } usbd_transfer_unsetup(sc->sc_xfer, AXGE_N_TRANSFER); uether_ifdetach(ue); + sx_destroy(&sc->sc_mii_lock); mtx_destroy(&sc->sc_mtx); return (0); @@ -768,7 +779,18 @@ mii = GET_MII(sc); AXGE_LOCK_ASSERT(sc, MA_OWNED); + AXGE_UNLOCK(sc); + if (!AXGE_MII_TRYLOCK(sc)) { + AXGE_LOCK(sc); + return; + } + AXGE_LOCK(sc); + mii_tick(mii); + + AXGE_UNLOCK(sc); + AXGE_MII_UNLOCK(sc); + AXGE_LOCK(sc); } static u_int diff --git a/sys/dev/usb/net/if_axgereg.h b/sys/dev/usb/net/if_axgereg.h --- a/sys/dev/usb/net/if_axgereg.h +++ b/sys/dev/usb/net/if_axgereg.h @@ -202,6 +202,7 @@ struct axge_softc { struct usb_ether sc_ue; struct mtx sc_mtx; + struct sx sc_mii_lock; struct usb_xfer *sc_xfer[AXGE_N_TRANSFER]; int sc_flags; @@ -214,3 +215,6 @@ #define AXGE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define AXGE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define AXGE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t) +#define AXGE_MII_LOCK(_sc) sx_xlock(&(_sc)->sc_mii_lock) +#define AXGE_MII_UNLOCK(_sc) sx_xunlock(&(_sc)->sc_mii_lock) +#define AXGE_MII_TRYLOCK(_sc) sx_try_xlock(&(_sc)->sc_mii_lock)