--- //depot/vendor/freebsd/src/sys/pci/if_ste.c 2005/08/17 14:40:38 +++ //depot/user/jhb/acpipci/pci/if_ste.c 2005/08/17 16:57:54 @@ -90,6 +90,7 @@ static int ste_attach(device_t); static int ste_detach(device_t); static void ste_init(void *); +static void ste_init_locked(struct ste_softc *); static void ste_intr(void *); static void ste_rxeoc(struct ste_softc *); static void ste_rxeof(struct ste_softc *); @@ -101,11 +102,13 @@ static int ste_ioctl(struct ifnet *, u_long, caddr_t); static int ste_encap(struct ste_softc *, struct ste_chain *, struct mbuf *); static void ste_start(struct ifnet *); +static void ste_start_locked(struct ifnet *); static void ste_watchdog(struct ifnet *); static void ste_shutdown(device_t); static int ste_newbuf(struct ste_softc *, struct ste_chain_onefrag *, struct mbuf *); static int ste_ifmedia_upd(struct ifnet *); +static void ste_ifmedia_upd_locked(struct ifnet *); static void ste_ifmedia_sts(struct ifnet *, struct ifmediareq *); static void ste_mii_sync(struct ste_softc *); @@ -246,7 +249,8 @@ { int i, ack; - STE_LOCK(sc); + if (sc->ste_ifp->if_input != NULL) + STE_LOCK_ASSERT(sc); /* * Set up frame for RX. @@ -321,8 +325,6 @@ MII_SET(STE_PHYCTL_MCLK); DELAY(1); - STE_UNLOCK(sc); - if (ack) return(1); return(0); @@ -337,7 +339,9 @@ struct ste_mii_frame *frame; { - STE_LOCK(sc); + + if (sc->ste_ifp->if_input != NULL) + STE_LOCK_ASSERT(sc); /* * Set up frame for TX. @@ -372,8 +376,6 @@ */ MII_CLR(STE_PHYCTL_MDIR); - STE_UNLOCK(sc); - return(0); } @@ -390,6 +392,9 @@ if ( sc->ste_one_phy && phy != 0 ) return (0); + if (sc->ste_ifp->if_input != NULL) + STE_LOCK_ASSERT(sc); + bzero((char *)&frame, sizeof(frame)); frame.mii_phyaddr = phy; @@ -410,6 +415,9 @@ sc = device_get_softc(dev); bzero((char *)&frame, sizeof(frame)); + if (sc->ste_ifp->if_input != NULL) + STE_LOCK_ASSERT(sc); + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; frame.mii_data = data; @@ -427,7 +435,10 @@ struct mii_data *mii; sc = device_get_softc(dev); - STE_LOCK(sc); + + if (sc->ste_ifp->if_input != NULL) + STE_LOCK_ASSERT(sc); + mii = device_get_softc(sc->ste_miibus); if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { @@ -435,7 +446,6 @@ } else { STE_CLRBIT2(sc, STE_MACCTL0, STE_MACCTL0_FULLDUPLEX); } - STE_UNLOCK(sc); return; } @@ -445,9 +455,24 @@ struct ifnet *ifp; { struct ste_softc *sc; + + sc = ifp->if_softc; + STE_LOCK(sc); + ste_ifmedia_upd_locked(ifp); + STE_UNLOCK(sc); + + return(0); +} + +static void +ste_ifmedia_upd_locked(ifp) + struct ifnet *ifp; +{ + struct ste_softc *sc; struct mii_data *mii; sc = ifp->if_softc; + STE_LOCK_ASSERT(sc); mii = device_get_softc(sc->ste_miibus); sc->ste_link = 0; if (mii->mii_instance) { @@ -456,8 +481,6 @@ mii_phy_reset(miisc); } mii_mediachg(mii); - - return(0); } static void @@ -471,9 +494,11 @@ sc = ifp->if_softc; mii = device_get_softc(sc->ste_miibus); + STE_LOCK(sc); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; + STE_UNLOCK(sc); return; } @@ -603,7 +628,7 @@ } #ifdef DEVICE_POLLING -static poll_handler_t ste_poll; +static poll_handler_t ste_poll, ste_poll_locked; static void ste_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) @@ -611,13 +636,23 @@ struct ste_softc *sc = ifp->if_softc; STE_LOCK(sc); + ste_poll_locked(ifp, cmd, count); + STE_UNLOCK(sc); +} + +static void +ste_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + struct ste_softc *sc = ifp->if_softc; + + STE_LOCK_ASSERT(sc); if (!(ifp->if_capenable & IFCAP_POLLING)) { ether_poll_deregister(ifp); cmd = POLL_DEREGISTER; } if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ CSR_WRITE_2(sc, STE_IMR, STE_INTRS); - goto done; + return; } sc->rxcycles = count; @@ -626,7 +661,7 @@ ste_rxeof(sc); ste_txeof(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - ste_start(ifp); + ste_start_locked(ifp); if (cmd == POLL_AND_CHECK_STATUS) { u_int16_t status; @@ -637,7 +672,7 @@ ste_txeoc(sc); if (status & STE_ISR_STATS_OFLOW) { - untimeout(ste_stats_update, sc, sc->ste_stat_ch); + callout_stop(&sc->ste_stat_callout); ste_stats_update(sc); } @@ -646,11 +681,9 @@ if (status & STE_ISR_HOSTERR) { ste_reset(sc); - ste_init(sc); + ste_init_locked(sc); } } -done: - STE_UNLOCK(sc); } #endif /* DEVICE_POLLING */ @@ -672,7 +705,7 @@ if ((ifp->if_capenable & IFCAP_POLLING) && ether_poll_register(ste_poll, ifp)) { /* ok, disable interrupts */ CSR_WRITE_2(sc, STE_IMR, 0); - ste_poll(ifp, 0, 1); + ste_poll_locked(ifp, 0, 1); goto done; } #endif /* DEVICE_POLLING */ @@ -701,7 +734,7 @@ ste_txeoc(sc); if (status & STE_ISR_STATS_OFLOW) { - untimeout(ste_stats_update, sc, sc->ste_stat_ch); + callout_stop(&sc->ste_stat_callout); ste_stats_update(sc); } @@ -711,7 +744,7 @@ if (status & STE_ISR_HOSTERR) { ste_reset(sc); - ste_init(sc); + ste_init_locked(sc); } } @@ -719,7 +752,7 @@ CSR_WRITE_2(sc, STE_IMR, STE_INTRS); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - ste_start(ifp); + ste_start_locked(ifp); #ifdef DEVICE_POLLING done: @@ -861,7 +894,7 @@ if_printf(ifp, "transmission error: %x\n", txstat); ste_reset(sc); - ste_init(sc); + ste_init_locked(sc); if (txstat & STE_TXSTATUS_UNDERRUN && sc->ste_tx_thresh < STE_PACKET_SIZE) { @@ -874,7 +907,7 @@ CSR_WRITE_2(sc, STE_TX_RECLAIM_THRESH, (STE_PACKET_SIZE >> 4)); } - ste_init(sc); + ste_init_locked(sc); CSR_WRITE_2(sc, STE_TX_STATUS, txstat); } @@ -920,7 +953,7 @@ struct mii_data *mii; sc = xsc; - STE_LOCK(sc); + STE_LOCK_ASSERT(sc); ifp = sc->ste_ifp; mii = device_get_softc(sc->ste_miibus); @@ -940,12 +973,11 @@ */ ste_miibus_statchg(sc->ste_dev); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - ste_start(ifp); + ste_start_locked(ifp); } } - sc->ste_stat_ch = timeout(ste_stats_update, sc, hz); - STE_UNLOCK(sc); + callout_reset(&sc->ste_stat_callout, hz, ste_stats_update, sc); return; } @@ -1002,7 +1034,7 @@ sc->ste_one_phy = 1; mtx_init(&sc->ste_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); /* * Map control/status registers. */ @@ -1031,7 +1063,7 @@ goto fail; } - callout_handle_init(&sc->ste_stat_ch); + callout_init_mtx(&sc->ste_stat_callout, &sc->ste_mtx, 0); /* Reset the adapter. */ ste_reset(sc); @@ -1076,8 +1108,7 @@ ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ste_ioctl; ifp->if_start = ste_start; ifp->if_watchdog = ste_watchdog; @@ -1105,7 +1136,7 @@ ifp->if_capenable = ifp->if_capabilities; /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET, + error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET | INTR_MPSAFE, ste_intr, sc, &sc->ste_intrhand); if (error) { @@ -1138,12 +1169,14 @@ sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->ste_mtx), ("ste mutex not initialized")); - STE_LOCK(sc); ifp = sc->ste_ifp; /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + STE_LOCK(sc); ste_stop(sc); + STE_UNLOCK(sc); + callout_drain(&sc->ste_stat_callout); ether_ifdetach(ifp); if_free(ifp); } @@ -1163,7 +1196,6 @@ M_DEVBUF); } - STE_UNLOCK(sc); mtx_destroy(&sc->ste_mtx); return(0); @@ -1271,11 +1303,21 @@ void *xsc; { struct ste_softc *sc; + + sc = xsc; + STE_LOCK(sc); + ste_init_locked(sc); + STE_UNLOCK(sc); +} + +static void +ste_init_locked(sc) + struct ste_softc *sc; +{ int i; struct ifnet *ifp; - sc = xsc; - STE_LOCK(sc); + STE_LOCK_ASSERT(sc); ifp = sc->ste_ifp; ste_stop(sc); @@ -1290,7 +1332,6 @@ if_printf(ifp, "initialization failed: no memory for RX buffers\n"); ste_stop(sc); - STE_UNLOCK(sc); return; } @@ -1370,13 +1411,12 @@ /* Accept VLAN length packets */ CSR_WRITE_2(sc, STE_MAX_FRAMELEN, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN); - ste_ifmedia_upd(ifp); + ste_ifmedia_upd_locked(ifp); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - sc->ste_stat_ch = timeout(ste_stats_update, sc, hz); - STE_UNLOCK(sc); + callout_reset(&sc->ste_stat_callout, hz, ste_stats_update, sc); return; } @@ -1388,10 +1428,10 @@ int i; struct ifnet *ifp; - STE_LOCK(sc); + STE_LOCK_ASSERT(sc); ifp = sc->ste_ifp; - untimeout(ste_stats_update, sc, sc->ste_stat_ch); + callout_stop(&sc->ste_stat_callout); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); #ifdef DEVICE_POLLING ether_poll_deregister(ifp); @@ -1427,7 +1467,6 @@ } bzero(sc->ste_ldata, sizeof(struct ste_list_data)); - STE_UNLOCK(sc); return; } @@ -1470,11 +1509,11 @@ int error = 0; sc = ifp->if_softc; - STE_LOCK(sc); ifr = (struct ifreq *)data; switch(command) { case SIOCSIFFLAGS: + STE_LOCK(sc); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_flags & IFF_PROMISC && @@ -1492,18 +1531,21 @@ ste_setmulti(sc); if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { sc->ste_tx_thresh = STE_TXSTART_THRESH; - ste_init(sc); + ste_init_locked(sc); } } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) ste_stop(sc); } sc->ste_if_flags = ifp->if_flags; + STE_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: + STE_LOCK(sc); ste_setmulti(sc); + STE_UNLOCK(sc); error = 0; break; case SIOCGIFMEDIA: @@ -1512,16 +1554,16 @@ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: + STE_LOCK(sc); ifp->if_capenable &= ~IFCAP_POLLING; ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; + STE_UNLOCK(sc); break; default: error = ether_ioctl(ifp, command, data); break; } - STE_UNLOCK(sc); - return(error); } @@ -1580,22 +1622,30 @@ struct ifnet *ifp; { struct ste_softc *sc; + + sc = ifp->if_softc; + STE_LOCK(sc); + ste_start_locked(ifp); + STE_UNLOCK(sc); +} + +static void +ste_start_locked(ifp) + struct ifnet *ifp; +{ + struct ste_softc *sc; struct mbuf *m_head = NULL; struct ste_chain *cur_tx; int idx; sc = ifp->if_softc; - STE_LOCK(sc); + STE_LOCK_ASSERT(sc); - if (!sc->ste_link) { - STE_UNLOCK(sc); + if (!sc->ste_link) return; - } - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - STE_UNLOCK(sc); + if (ifp->if_drv_flags & IFF_DRV_OACTIVE) return; - } idx = sc->ste_cdata.ste_tx_prod; @@ -1654,8 +1704,6 @@ } sc->ste_cdata.ste_tx_prod = idx; - STE_UNLOCK(sc); - return; } @@ -1676,10 +1724,10 @@ ste_rxeoc(sc); ste_rxeof(sc); ste_reset(sc); - ste_init(sc); + ste_init_locked(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - ste_start(ifp); + ste_start_locked(ifp); STE_UNLOCK(sc); return; @@ -1693,7 +1741,9 @@ sc = device_get_softc(dev); + STE_LOCK(sc); ste_stop(sc); + STE_UNLOCK(sc); return; } --- //depot/vendor/freebsd/src/sys/pci/if_stereg.h 2005/08/17 14:40:38 +++ //depot/user/jhb/acpipci/pci/if_stereg.h 2005/08/17 16:57:54 @@ -519,7 +519,7 @@ struct ste_chain *ste_tx_prev; struct ste_list_data *ste_ldata; struct ste_chain_data ste_cdata; - struct callout_handle ste_stat_ch; + struct callout ste_stat_callout; struct mtx ste_mtx; u_int8_t ste_one_phy; #ifdef DEVICE_POLLING