--- //depot/vendor/freebsd/src/sys/pci/if_sf.c 2005/08/10 20:25:25 +++ //depot/user/jhb/acpipci/pci/if_sf.c 2005/08/17 17:59:12 @@ -137,12 +137,15 @@ static int sf_encap(struct sf_softc *, struct sf_tx_bufdesc_type0 *, struct mbuf *); static void sf_start(struct ifnet *); +static void sf_start_locked(struct ifnet *); static int sf_ioctl(struct ifnet *, u_long, caddr_t); static void sf_init(void *); +static void sf_init_locked(struct sf_softc *); static void sf_stop(struct sf_softc *); static void sf_watchdog(struct ifnet *); static void sf_shutdown(device_t); static int sf_ifmedia_upd(struct ifnet *); +static void sf_ifmedia_upd_locked(struct ifnet *); static void sf_ifmedia_sts(struct ifnet *, struct ifmediareq *); static void sf_reset(struct sf_softc *); static int sf_init_rx_ring(struct sf_softc *); @@ -350,6 +353,8 @@ u_int32_t val = 0; sc = device_get_softc(dev); + if (sc->sf_ifp->if_input != NULL) + SF_LOCK_ASSERT(sc); for (i = 0; i < SF_TIMEOUT; i++) { val = csr_read_4(sc, SF_PHY_REG(phy, reg)); @@ -376,6 +381,8 @@ int busy; sc = device_get_softc(dev); + if (sc->sf_ifp->if_input != NULL) + SF_LOCK_ASSERT(sc); csr_write_4(sc, SF_PHY_REG(phy, reg), val); @@ -397,6 +404,8 @@ sc = device_get_softc(dev); mii = device_get_softc(sc->sf_miibus); + if (sc->sf_ifp->if_input != NULL) + SF_LOCK_ASSERT(sc); if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); @@ -462,10 +471,25 @@ struct ifnet *ifp; { struct sf_softc *sc; + + sc = ifp->if_softc; + SF_LOCK(sc); + sf_ifmedia_upd_locked(ifp); + SF_UNLOCK(sc); + + return(0); +} + +static void +sf_ifmedia_upd_locked(ifp) + struct ifnet *ifp; +{ + struct sf_softc *sc; struct mii_data *mii; sc = ifp->if_softc; mii = device_get_softc(sc->sf_miibus); + SF_LOCK_ASSERT(sc); sc->sf_link = 0; if (mii->mii_instance) { struct mii_softc *miisc; @@ -473,8 +497,6 @@ mii_phy_reset(miisc); } mii_mediachg(mii); - - return(0); } /* @@ -489,11 +511,13 @@ struct mii_data *mii; sc = ifp->if_softc; + SF_LOCK(sc); mii = device_get_softc(sc->sf_miibus); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; + SF_UNLOCK(sc); } static int @@ -507,10 +531,9 @@ struct mii_data *mii; int error = 0; - SF_LOCK(sc); - switch(command) { case SIOCSIFFLAGS: + SF_LOCK(sc); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_flags & IFF_PROMISC && @@ -521,17 +544,20 @@ sc->sf_if_flags & IFF_PROMISC) { SF_CLRBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC); } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - sf_init(sc); + sf_init_locked(sc); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) sf_stop(sc); } sc->sf_if_flags = ifp->if_flags; + SF_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: + SF_LOCK(sc); sf_setmulti(sc); + SF_UNLOCK(sc); error = 0; break; case SIOCGIFMEDIA: @@ -540,16 +566,16 @@ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: + SF_LOCK(sc); ifp->if_capenable &= ~IFCAP_POLLING; ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; + SF_UNLOCK(sc); break; default: error = ether_ioctl(ifp, command, data); break; } - SF_UNLOCK(sc); - return(error); } @@ -649,7 +675,7 @@ sc = device_get_softc(dev); mtx_init(&sc->sf_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); /* * Map control/status registers. */ @@ -678,7 +704,8 @@ goto fail; } - callout_handle_init(&sc->sf_stat_ch); + callout_init_mtx(&sc->sf_stat_callout, &sc->sf_mtx, 0); + /* Reset the adapter. */ sf_reset(sc); @@ -719,8 +746,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 = sf_ioctl; ifp->if_start = sf_start; ifp->if_watchdog = sf_watchdog; @@ -740,7 +766,7 @@ ether_ifattach(ifp, eaddr); /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->sf_irq, INTR_TYPE_NET, + error = bus_setup_intr(dev, sc->sf_irq, INTR_TYPE_NET | INTR_MPSAFE, sf_intr, sc, &sc->sf_intrhand); if (error) { @@ -773,12 +799,14 @@ sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->sf_mtx), ("sf mutex not initialized")); - SF_LOCK(sc); ifp = sc->sf_ifp; /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + SF_LOCK(sc); sf_stop(sc); + SF_UNLOCK(sc); + callout_drain(&sc->sf_stat_callout); ether_ifdetach(ifp); if_free(ifp); } @@ -796,7 +824,6 @@ if (sc->sf_ldata) contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF); - SF_UNLOCK(sc); mtx_destroy(&sc->sf_mtx); return(0); @@ -984,6 +1011,7 @@ ifp = sc->sf_ifp; + SF_LOCK_ASSERT(sc); txcons = csr_read_4(sc, SF_CQ_CONSIDX); cmpprodidx = SF_IDX_HI(csr_read_4(sc, SF_CQ_PRODIDX)); cmpconsidx = SF_IDX_HI(txcons); @@ -1072,7 +1100,7 @@ sf_rxeof(sc); sf_txeof(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - sf_start(ifp); + sf_start_locked(ifp); if (cmd == POLL_AND_CHECK_STATUS) { u_int32_t status; @@ -1086,11 +1114,10 @@ if (status & SF_ISR_ABNORMALINTR) { if (status & SF_ISR_STATSOFLOW) { - untimeout(sf_stats_update, sc, - sc->sf_stat_ch); + callout_stop(&sc->sf_stat_callout); sf_stats_update(sc); } else - sf_init(sc); + sf_init_locked(sc); } } } @@ -1151,11 +1178,10 @@ if (status & SF_ISR_ABNORMALINTR) { if (status & SF_ISR_STATSOFLOW) { - untimeout(sf_stats_update, sc, - sc->sf_stat_ch); + callout_stop(&sc->sf_stat_callout); sf_stats_update(sc); } else - sf_init(sc); + sf_init_locked(sc); } } @@ -1163,7 +1189,7 @@ csr_write_4(sc, SF_IMR, SF_INTRS); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - sf_start(ifp); + sf_start_locked(ifp); #ifdef DEVICE_POLLING done_locked: @@ -1176,12 +1202,22 @@ void *xsc; { struct sf_softc *sc; + + sc = xsc; + SF_LOCK(sc); + sf_init_locked(sc); + SF_UNLOCK(sc); +} + +static void +sf_init_locked(sc) + struct sf_softc *sc; +{ struct ifnet *ifp; struct mii_data *mii; int i; - sc = xsc; - SF_LOCK(sc); + SF_LOCK_ASSERT(sc); ifp = sc->sf_ifp; mii = device_get_softc(sc->sf_miibus); @@ -1206,7 +1242,6 @@ if (sf_init_rx_ring(sc) == ENOBUFS) { if_printf(sc->sf_ifp, "initialization failed: no memory for rx buffers\n"); - SF_UNLOCK(sc); return; } @@ -1281,14 +1316,12 @@ SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB); /*mii_mediachg(mii);*/ - sf_ifmedia_upd(ifp); + sf_ifmedia_upd_locked(ifp); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - sc->sf_stat_ch = timeout(sf_stats_update, sc, hz); - - SF_UNLOCK(sc); + callout_reset(&sc->sf_stat_callout, hz, sf_stats_update, sc); } static int @@ -1359,29 +1392,37 @@ struct ifnet *ifp; { struct sf_softc *sc; + + sc = ifp->if_softc; + SF_LOCK(sc); + sf_start_locked(ifp); + SF_UNLOCK(sc); +} + +static void +sf_start_locked(ifp) + struct ifnet *ifp; +{ + struct sf_softc *sc; struct sf_tx_bufdesc_type0 *cur_tx = NULL; struct mbuf *m_head = NULL; int i, txprod; sc = ifp->if_softc; - SF_LOCK(sc); + SF_LOCK_ASSERT(sc); - if (!sc->sf_link && ifp->if_snd.ifq_len < 10) { - SF_UNLOCK(sc); + if (!sc->sf_link && ifp->if_snd.ifq_len < 10) return; - } - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - SF_UNLOCK(sc); + if (ifp->if_drv_flags & IFF_DRV_OACTIVE) return; - } txprod = csr_read_4(sc, SF_TXDQ_PRODIDX); i = SF_IDX_HI(txprod) >> 4; if (sc->sf_ldata->sf_tx_dlist[i].sf_mbuf != NULL) { if_printf(ifp, "TX ring full, resetting\n"); - sf_init(sc); + sf_init_locked(sc); txprod = csr_read_4(sc, SF_TXDQ_PRODIDX); i = SF_IDX_HI(txprod) >> 4; } @@ -1419,10 +1460,8 @@ break; } - if (cur_tx == NULL) { - SF_UNLOCK(sc); + if (cur_tx == NULL) return; - } /* Transmit */ csr_write_4(sc, SF_TXDQ_PRODIDX, @@ -1430,8 +1469,6 @@ ((i << 20) & 0xFFFF0000)); ifp->if_timer = 5; - - SF_UNLOCK(sc); } static void @@ -1441,11 +1478,11 @@ int i; struct ifnet *ifp; - SF_LOCK(sc); + SF_LOCK_ASSERT(sc); ifp = sc->sf_ifp; - untimeout(sf_stats_update, sc, sc->sf_stat_ch); + callout_stop(&sc->sf_stat_callout); #ifdef DEVICE_POLLING ether_poll_deregister(ifp); @@ -1479,7 +1516,6 @@ } ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); - SF_UNLOCK(sc); } /* @@ -1501,7 +1537,7 @@ int i; sc = xsc; - SF_LOCK(sc); + SF_LOCK_ASSERT(sc); ifp = sc->sf_ifp; mii = device_get_softc(sc->sf_miibus); @@ -1523,12 +1559,10 @@ IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->sf_link++; if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - sf_start(ifp); + sf_start_locked(ifp); } - sc->sf_stat_ch = timeout(sf_stats_update, sc, hz); - - SF_UNLOCK(sc); + callout_reset(&sc->sf_stat_callout, hz, sf_stats_update, sc); } static void @@ -1546,10 +1580,10 @@ sf_stop(sc); sf_reset(sc); - sf_init(sc); + sf_init_locked(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - sf_start(ifp); + sf_start_locked(ifp); SF_UNLOCK(sc); } @@ -1562,5 +1596,7 @@ sc = device_get_softc(dev); + SF_LOCK(sc); sf_stop(sc); + SF_UNLOCK(sc); } --- //depot/vendor/freebsd/src/sys/pci/if_sfreg.h 2005/08/10 20:25:25 +++ //depot/user/jhb/acpipci/pci/if_sfreg.h 2005/08/10 20:45:43 @@ -1043,7 +1043,7 @@ int sf_tx_cnt; u_int8_t sf_link; int sf_if_flags; - struct callout_handle sf_stat_ch; + struct callout sf_stat_callout; struct mtx sf_mtx; #ifdef DEVICE_POLLING int rxcycles;