--- //depot/vendor/freebsd/src/sys/pci/if_tl.c 2005/08/09 10:22:44 +++ //depot/user/jhb/acpipci/pci/if_tl.c 2005/08/31 15:34:42 @@ -276,8 +276,10 @@ static void tl_intr(void *); static void tl_start(struct ifnet *); +static void tl_start_locked(struct ifnet *); static int tl_ioctl(struct ifnet *, u_long, caddr_t); static void tl_init(void *); +static void tl_init_locked(struct tl_softc *); static void tl_stop(struct tl_softc *); static void tl_watchdog(struct ifnet *); static void tl_shutdown(device_t); @@ -650,7 +652,8 @@ int i, ack; int minten = 0; - TL_LOCK(sc); + if (sc->tl_ifp->if_input != NULL) + TL_LOCK_ASSERT(sc); tl_mii_sync(sc); @@ -730,8 +733,6 @@ tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MINTEN); } - TL_UNLOCK(sc); - if (ack) return(1); return(0); @@ -745,7 +746,8 @@ { int minten; - TL_LOCK(sc); + if (sc->tl_ifp->if_input != NULL) + TL_LOCK_ASSERT(sc); tl_mii_sync(sc); @@ -789,8 +791,6 @@ if (minten) tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MINTEN); - TL_UNLOCK(sc); - return(0); } @@ -840,7 +840,8 @@ struct mii_data *mii; sc = device_get_softc(dev); - TL_LOCK(sc); + if (sc->tl_ifp->if_input != NULL) + TL_LOCK_ASSERT(sc); mii = device_get_softc(sc->tl_miibus); if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { @@ -848,7 +849,6 @@ } else { tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_DUPLEX); } - TL_UNLOCK(sc); return; } @@ -1138,7 +1138,7 @@ } mtx_init(&sc->tl_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); /* * Map control/status registers. @@ -1267,15 +1267,14 @@ } ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = tl_ioctl; ifp->if_start = tl_start; ifp->if_watchdog = tl_watchdog; ifp->if_init = tl_init; ifp->if_mtu = ETHERMTU; ifp->if_snd.ifq_maxlen = TL_TX_LIST_CNT - 1; - callout_handle_init(&sc->tl_stat_ch); + callout_init_mtx(&sc->tl_stat_callout, &sc->tl_mtx, 0); /* Reset the adapter again. */ tl_softreset(sc, 1); @@ -1310,7 +1309,7 @@ ether_ifattach(ifp, eaddr); /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->tl_irq, INTR_TYPE_NET, + error = bus_setup_intr(dev, sc->tl_irq, INTR_TYPE_NET | INTR_MPSAFE, tl_intr, sc, &sc->tl_intrhand); if (error) { @@ -1343,12 +1342,14 @@ sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->tl_mtx), ("tl mutex not initialized")); - TL_LOCK(sc); ifp = sc->tl_ifp; /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + TL_LOCK(sc); tl_stop(sc); + TL_UNLOCK(sc); + callout_drain(&sc->tl_stat_callout); ether_ifdetach(ifp); if_free(ifp); } @@ -1368,7 +1369,6 @@ if (sc->tl_res) bus_release_resource(dev, TL_RES, TL_RID, sc->tl_res); - TL_UNLOCK(sc); mtx_destroy(&sc->tl_mtx); return(0); @@ -1444,16 +1444,10 @@ { struct mbuf *m_new = NULL; - MGETHDR(m_new, M_DONTWAIT, MT_DATA); + m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); if (m_new == NULL) return(ENOBUFS); - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - m_freem(m_new); - return(ENOBUFS); - } - #ifdef __alpha__ m_new->m_data += 2; #endif @@ -1691,7 +1685,7 @@ tl_softreset(sc, 1); tl_stop(sc); - tl_init(sc); + tl_init_locked(sc); CMD_SET(sc, TL_CMD_INTSON); return(0); @@ -1784,7 +1778,7 @@ } if (ifp->if_snd.ifq_head != NULL) - tl_start(ifp); + tl_start_locked(ifp); TL_UNLOCK(sc); @@ -1804,7 +1798,7 @@ bzero((char *)&tl_stats, sizeof(struct tl_stats)); sc = xsc; - TL_LOCK(sc); + TL_LOCK_ASSERT(sc); ifp = sc->tl_ifp; p = (u_int32_t *)&tl_stats; @@ -1838,15 +1832,13 @@ } } - sc->tl_stat_ch = timeout(tl_stats_update, sc, hz); + callout_reset(&sc->tl_stat_callout, hz, tl_stats_update, sc); if (!sc->tl_bitrate) { mii = device_get_softc(sc->tl_miibus); mii_tick(mii); } - TL_UNLOCK(sc); - return; } @@ -1957,12 +1949,24 @@ struct ifnet *ifp; { struct tl_softc *sc; + + sc = ifp->if_softc; + TL_LOCK(sc); + tl_start_locked(ifp); + TL_UNLOCK(sc); +} + +static void +tl_start_locked(ifp) + struct ifnet *ifp; +{ + struct tl_softc *sc; struct mbuf *m_head = NULL; u_int32_t cmd; struct tl_chain *prev = NULL, *cur_tx = NULL, *start_tx; sc = ifp->if_softc; - TL_LOCK(sc); + TL_LOCK_ASSERT(sc); /* * Check for an available queue slot. If there are none, @@ -1970,7 +1974,6 @@ */ if (sc->tl_cdata.tl_tx_free == NULL) { ifp->if_drv_flags |= IFF_DRV_OACTIVE; - TL_UNLOCK(sc); return; } @@ -2007,10 +2010,8 @@ /* * If there are no packets queued, bail. */ - if (cur_tx == NULL) { - TL_UNLOCK(sc); + if (cur_tx == NULL) return; - } /* * That's all we can stands, we can't stands no more. @@ -2040,7 +2041,6 @@ * Set a timeout in case the chip goes out to lunch. */ ifp->if_timer = 5; - TL_UNLOCK(sc); return; } @@ -2050,10 +2050,20 @@ void *xsc; { struct tl_softc *sc = xsc; + + TL_LOCK(sc); + tl_init_locked(sc); + TL_UNLOCK(sc); +} + +static void +tl_init_locked(sc) + struct tl_softc *sc; +{ struct ifnet *ifp = sc->tl_ifp; struct mii_data *mii; - TL_LOCK(sc); + TL_LOCK_ASSERT(sc); ifp = sc->tl_ifp; @@ -2098,7 +2108,6 @@ if_printf(ifp, "initialization failed: no memory for rx buffers\n"); tl_stop(sc); - TL_UNLOCK(sc); return; } @@ -2128,8 +2137,7 @@ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* Start the stats update counter */ - sc->tl_stat_ch = timeout(tl_stats_update, sc, hz); - TL_UNLOCK(sc); + callout_reset(&sc->tl_stat_callout, hz, tl_stats_update, sc); return; } @@ -2146,12 +2154,14 @@ sc = ifp->if_softc; + TL_LOCK(sc); if (sc->tl_bitrate) tl_setmode(sc, sc->ifmedia.ifm_media); else { mii = device_get_softc(sc->tl_miibus); mii_mediachg(mii); } + TL_UNLOCK(sc); return(0); } @@ -2169,6 +2179,7 @@ sc = ifp->if_softc; + TL_LOCK(sc); ifmr->ifm_active = IFM_ETHER; if (sc->tl_bitrate) { @@ -2187,6 +2198,7 @@ ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; } + TL_UNLOCK(sc); return; } @@ -2199,12 +2211,11 @@ { struct tl_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; - int s, error = 0; - - s = splimp(); + int error = 0; switch(command) { case SIOCSIFFLAGS: + TL_LOCK(sc); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_flags & IFF_PROMISC && @@ -2217,18 +2228,21 @@ tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_CAF); tl_setmulti(sc); } else - tl_init(sc); + tl_init_locked(sc); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { tl_stop(sc); } } sc->tl_if_flags = ifp->if_flags; + TL_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: + TL_LOCK(sc); tl_setmulti(sc); + TL_UNLOCK(sc); error = 0; break; case SIOCSIFMEDIA: @@ -2247,8 +2261,6 @@ break; } - (void)splx(s); - return(error); } @@ -2262,10 +2274,12 @@ if_printf(ifp, "device timeout\n"); + TL_LOCK(sc); ifp->if_oerrors++; tl_softreset(sc, 1); - tl_init(sc); + tl_init_locked(sc); + TL_UNLOCK(sc); return; } @@ -2281,12 +2295,12 @@ register int i; struct ifnet *ifp; - TL_LOCK(sc); + TL_LOCK_ASSERT(sc); ifp = sc->tl_ifp; /* Stop the stats updater. */ - untimeout(tl_stats_update, sc, sc->tl_stat_ch); + callout_stop(&sc->tl_stat_callout); /* Stop the transmitter */ CMD_CLR(sc, TL_CMD_RT); @@ -2333,7 +2347,6 @@ sizeof(sc->tl_ldata->tl_tx_list)); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - TL_UNLOCK(sc); return; } @@ -2350,7 +2363,9 @@ sc = device_get_softc(dev); + TL_LOCK(sc); tl_stop(sc); + TL_UNLOCK(sc); return; } --- //depot/vendor/freebsd/src/sys/pci/if_tlreg.h 2005/06/10 16:51:34 +++ //depot/user/jhb/acpipci/pci/if_tlreg.h 2005/08/31 15:11:41 @@ -124,7 +124,7 @@ u_int8_t tl_txeoc; u_int8_t tl_bitrate; int tl_if_flags; - struct callout_handle tl_stat_ch; + struct callout tl_stat_callout; struct mtx tl_mtx; };