--- a/sys/dev/netif/bfe/if_bfe.c +++ b/sys/dev/netif/bfe/if_bfe.c @@ -1491,21 +1491,30 @@ mii = device_get_softc(sc->bfe_miibus); - lwkt_serialize_enter(ifp->if_serializer); + /* + * Never block on the serializer here. bfe_stop() tears this + * callout down with callout_stop() while holding the same + * serializer, and callout_stop() synchronously waits for an + * in-progress callback (kern_timeout.c "costp" wait). A + * callback blocked in lwkt_serialize_enter() therefore + * deadlocks the softclock thread against the serializer + * holder (AB-BA). Use try-enter and retry on the next tick. + */ + if (lwkt_serialize_try(ifp->if_serializer)) { + bfe_stats_update(sc); - bfe_stats_update(sc); - callout_reset(&sc->bfe_stat_timer, hz, bfe_tick, sc); - - if (sc->bfe_link == 0) { - mii_tick(mii); - if (!sc->bfe_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->bfe_link++; + if (sc->bfe_link == 0) { + mii_tick(mii); + if (!sc->bfe_link && mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + sc->bfe_link++; + } + if (!sc->bfe_link) + sc->bfe_link++; } - if (!sc->bfe_link) - sc->bfe_link++; + lwkt_serialize_exit(ifp->if_serializer); } - lwkt_serialize_exit(ifp->if_serializer); + callout_reset(&sc->bfe_stat_timer, hz, bfe_tick, sc); } /*