--- //depot/vendor/freebsd/src/sys/pci/if_pcn.c 2005/06/10 16:51:34 +++ //depot/user/jhb/acpipci/pci/if_pcn.c 2005/07/30 16:03:41 @@ -143,8 +143,10 @@ static void pcn_intr(void *); static void pcn_tick(void *); static void pcn_start(struct ifnet *); +static void pcn_start_locked(struct ifnet *); static int pcn_ioctl(struct ifnet *, u_long, caddr_t); static void pcn_init(void *); +static void pcn_init_locked(struct pcn_softc *); static void pcn_stop(struct pcn_softc *); static void pcn_watchdog(struct ifnet *); static void pcn_shutdown(device_t); @@ -540,7 +542,7 @@ /* Initialize our mutex. */ mtx_init(&sc->pcn_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); /* * Map control/status registers. */ @@ -584,7 +586,7 @@ eaddr[1] = CSR_READ_4(sc, PCN_IO32_APROM01); sc->pcn_unit = unit; - callout_handle_init(&sc->pcn_stat_ch); + callout_init(&sc->pcn_stat_callout, 0); sc->pcn_ldata = contigmalloc(sizeof(struct pcn_list_data), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0); @@ -665,12 +667,14 @@ ifp = sc->pcn_ifp; KASSERT(mtx_initialized(&sc->pcn_mtx), ("pcn mutex not initialized")); - PCN_LOCK(sc); /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + PCN_LOCK(sc); pcn_reset(sc); pcn_stop(sc); + PCN_UNLOCK(sc); + callout_drain(&sc->pcn_stat_callout); ether_ifdetach(ifp); if_free(ifp); } @@ -689,7 +693,6 @@ contigfree(sc->pcn_ldata, sizeof(struct pcn_list_data), M_DEVBUF); } - PCN_UNLOCK(sc); mtx_destroy(&sc->pcn_mtx); @@ -923,6 +926,10 @@ sc = xsc; ifp = sc->pcn_ifp; PCN_LOCK(sc); + if (!(ifp->if_flags & IFF_RUNNING)) { + PCN_UNLOCK(sc); + return; + } mii = device_get_softc(sc->pcn_miibus); mii_tick(mii); @@ -936,10 +943,10 @@ IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->pcn_link++; if (ifp->if_snd.ifq_head != NULL) - pcn_start(ifp); + pcn_start_locked(ifp); } - sc->pcn_stat_ch = timeout(pcn_tick, sc, hz); + callout_reset(&sc->pcn_stat_callout, hz, pcn_tick, sc); PCN_UNLOCK(sc); @@ -957,14 +964,15 @@ sc = arg; ifp = sc->pcn_ifp; + PCN_LOCK(sc); + /* Suppress unwanted interrupts */ if (!(ifp->if_flags & IFF_UP)) { pcn_stop(sc); + PCN_UNLOCK(sc); return; } - PCN_LOCK(sc); - CSR_WRITE_4(sc, PCN_IO32_RAP, PCN_CSR_CSR); while ((status = CSR_READ_4(sc, PCN_IO32_RDP)) & PCN_CSR_INTR) { @@ -977,13 +985,13 @@ pcn_txeof(sc); if (status & PCN_CSR_ERR) { - pcn_init(sc); + pcn_init_locked(sc); break; } } if (ifp->if_snd.ifq_head != NULL) - pcn_start(ifp); + pcn_start_locked(ifp); PCN_UNLOCK(sc); return; @@ -1054,24 +1062,32 @@ struct ifnet *ifp; { struct pcn_softc *sc; + + sc = ifp->if_softc; + PCN_LOCK(sc); + pcn_start_locked(ifp); + PCN_UNLOCK(sc); +} + +static void +pcn_start_locked(ifp) + struct ifnet *ifp; +{ + struct pcn_softc *sc; struct mbuf *m_head = NULL; u_int32_t idx; sc = ifp->if_softc; - PCN_LOCK(sc); + PCN_LOCK_ASSERT(sc); - if (!sc->pcn_link) { - PCN_UNLOCK(sc); + if (!sc->pcn_link) return; - } idx = sc->pcn_cdata.pcn_tx_prod; - if (ifp->if_flags & IFF_OACTIVE) { - PCN_UNLOCK(sc); + if (ifp->if_flags & IFF_OACTIVE) return; - } while(sc->pcn_cdata.pcn_tx_chain[idx] == NULL) { IF_DEQUEUE(&ifp->if_snd, m_head); @@ -1101,8 +1117,6 @@ */ ifp->if_timer = 5; - PCN_UNLOCK(sc); - return; } @@ -1136,10 +1150,20 @@ void *xsc; { struct pcn_softc *sc = xsc; + + PCN_LOCK(sc); + pcn_init_locked(sc); + PCN_UNLOCK(sc); +} + +static void +pcn_init_locked(sc) + struct pcn_softc *sc; +{ struct ifnet *ifp = sc->pcn_ifp; struct mii_data *mii = NULL; - PCN_LOCK(sc); + PCN_LOCK_ASSERT(sc); /* * Cancel pending I/O and free all RX/TX buffers. @@ -1162,7 +1186,6 @@ printf("pcn%d: initialization failed: no " "memory for rx buffers\n", sc->pcn_unit); pcn_stop(sc); - PCN_UNLOCK(sc); return; } @@ -1233,8 +1256,7 @@ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - sc->pcn_stat_ch = timeout(pcn_tick, sc, hz); - PCN_UNLOCK(sc); + callout_reset(&sc->pcn_stat_callout, hz, pcn_tick, sc); return; } @@ -1252,6 +1274,7 @@ sc = ifp->if_softc; mii = device_get_softc(sc->pcn_miibus); + PCN_LOCK(sc); sc->pcn_link = 0; if (mii->mii_instance) { struct mii_softc *miisc; @@ -1259,6 +1282,7 @@ mii_phy_reset(miisc); } mii_mediachg(mii); + PCN_UNLOCK(sc); return(0); } @@ -1277,9 +1301,11 @@ sc = ifp->if_softc; mii = device_get_softc(sc->pcn_miibus); + PCN_LOCK(sc); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; + PCN_UNLOCK(sc); return; } @@ -1295,10 +1321,9 @@ struct mii_data *mii = NULL; int error = 0; - PCN_LOCK(sc); - switch(command) { case SIOCSIFFLAGS: + PCN_LOCK(sc); if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_RUNNING && ifp->if_flags & IFF_PROMISC && @@ -1321,17 +1346,20 @@ pcn_csr_write(sc, PCN_CSR_CSR, PCN_CSR_INTEN|PCN_CSR_START); } else if (!(ifp->if_flags & IFF_RUNNING)) - pcn_init(sc); + pcn_init_locked(sc); } else { if (ifp->if_flags & IFF_RUNNING) pcn_stop(sc); } sc->pcn_if_flags = ifp->if_flags; + PCN_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: + PCN_LOCK(sc); pcn_setmulti(sc); + PCN_UNLOCK(sc); error = 0; break; case SIOCGIFMEDIA: @@ -1344,8 +1372,6 @@ break; } - PCN_UNLOCK(sc); - return(error); } @@ -1364,7 +1390,7 @@ pcn_stop(sc); pcn_reset(sc); - pcn_init(sc); + pcn_init_locked(sc); if (ifp->if_snd.ifq_head != NULL) pcn_start(ifp); @@ -1385,11 +1411,11 @@ register int i; struct ifnet *ifp; + PCN_LOCK_ASSERT(sc); ifp = sc->pcn_ifp; - PCN_LOCK(sc); ifp->if_timer = 0; - untimeout(pcn_tick, sc, sc->pcn_stat_ch); + callout_stop(&sc->pcn_stat_callout); /* Turn off interrupts */ PCN_CSR_CLRBIT(sc, PCN_CSR_CSR, PCN_CSR_INTEN); @@ -1423,7 +1449,6 @@ sizeof(sc->pcn_ldata->pcn_tx_list)); ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - PCN_UNLOCK(sc); return; } --- //depot/vendor/freebsd/src/sys/pci/if_pcnreg.h 2005/06/10 16:51:34 +++ //depot/user/jhb/acpipci/pci/if_pcnreg.h 2005/07/30 16:03:41 @@ -465,7 +465,7 @@ int pcn_type; struct pcn_list_data *pcn_ldata; struct pcn_ring_data pcn_cdata; - struct callout_handle pcn_stat_ch; + struct callout pcn_stat_callout; struct mtx pcn_mtx; };