diff options
Diffstat (limited to 'sys/dev/ic/dc.c')
-rw-r--r-- | sys/dev/ic/dc.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/sys/dev/ic/dc.c b/sys/dev/ic/dc.c index c992cb13613..ffc5ad11849 100644 --- a/sys/dev/ic/dc.c +++ b/sys/dev/ic/dc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dc.c,v 1.112 2009/08/10 20:29:54 deraadt Exp $ */ +/* $OpenBSD: dc.c,v 1.113 2009/10/15 17:54:54 deraadt Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -145,7 +145,7 @@ void dc_tx_underrun(struct dc_softc *); void dc_start(struct ifnet *); int dc_ioctl(struct ifnet *, u_long, caddr_t); void dc_init(void *); -void dc_stop(struct dc_softc *); +void dc_stop(struct dc_softc *, int); void dc_watchdog(struct ifnet *); int dc_ifmedia_upd(struct ifnet *); void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -2465,20 +2465,23 @@ dc_intr(void *arg) { struct dc_softc *sc; struct ifnet *ifp; - u_int32_t status; + u_int32_t status, ints; int claimed = 0; sc = arg; ifp = &sc->sc_arpcom.ac_if; - if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0) + ints = CSR_READ_4(sc, DC_ISR); + if ((ints & DC_INTRS) == 0) return (claimed); + if (ints == 0xffffffff) + return (0); /* Suppress unwanted interrupts */ if (!(ifp->if_flags & IFF_UP)) { if (CSR_READ_4(sc, DC_ISR) & DC_INTRS) - dc_stop(sc); + dc_stop(sc, 0); return (claimed); } @@ -2750,7 +2753,7 @@ dc_init(void *xsc) /* * Cancel pending I/O and free all RX/TX buffers. */ - dc_stop(sc); + dc_stop(sc, 0); dc_reset(sc); /* @@ -2834,7 +2837,7 @@ dc_init(void *xsc) if (dc_list_rx_init(sc) == ENOBUFS) { printf("%s: initialization failed: no " "memory for rx buffers\n", sc->sc_dev.dv_xname); - dc_stop(sc); + dc_stop(sc, 0); splx(s); return; } @@ -3006,7 +3009,7 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } } else { if (ifp->if_flags & IFF_RUNNING) - dc_stop(sc); + dc_stop(sc, 0); } sc->dc_if_flags = ifp->if_flags; break; @@ -3043,7 +3046,7 @@ dc_watchdog(struct ifnet *ifp) ifp->if_oerrors++; printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); - dc_stop(sc); + dc_stop(sc, 0); dc_reset(sc); dc_init(sc); @@ -3056,7 +3059,7 @@ dc_watchdog(struct ifnet *ifp) * RX and TX lists. */ void -dc_stop(struct dc_softc *sc) +dc_stop(struct dc_softc *sc, int softonly) { struct ifnet *ifp; int i; @@ -3068,11 +3071,13 @@ dc_stop(struct dc_softc *sc) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON|DC_NETCFG_TX_ON)); - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - CSR_WRITE_4(sc, DC_TXADDR, 0x00000000); - CSR_WRITE_4(sc, DC_RXADDR, 0x00000000); - sc->dc_link = 0; + if (!softonly) { + DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON|DC_NETCFG_TX_ON)); + CSR_WRITE_4(sc, DC_IMR, 0x00000000); + CSR_WRITE_4(sc, DC_TXADDR, 0x00000000); + CSR_WRITE_4(sc, DC_RXADDR, 0x00000000); + sc->dc_link = 0; + } /* * Free data in the RX lists. @@ -3131,7 +3136,7 @@ dc_power(int why, void *arg) s = splnet(); if (why != PWR_RESUME) - dc_stop(sc); + dc_stop(sc, 0); else { ifp = &sc->sc_arpcom.ac_if; if (ifp->if_flags & IFF_UP) @@ -3144,6 +3149,9 @@ int dc_detach(struct dc_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; + int i; + + dc_stop(sc, 1); if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL) mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); @@ -3151,7 +3159,20 @@ dc_detach(struct dc_softc *sc) if (sc->dc_srom) free(sc->dc_srom, M_DEVBUF); - timeout_del(&sc->dc_tick_tmo); + for (i = 0; i < DC_RX_LIST_CNT; i++) + bus_dmamap_destroy(sc->sc_dmat, sc->dc_cdata.dc_rx_chain[i].sd_map); + if (sc->sc_rx_sparemap) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_sparemap); + for (i = 0; i < DC_TX_LIST_CNT; i++) + bus_dmamap_destroy(sc->sc_dmat, sc->dc_cdata.dc_tx_chain[i].sd_map); + if (sc->sc_tx_sparemap) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_sparemap); + + /// XXX bus_dmamap_sync + bus_dmamap_unload(sc->sc_dmat, sc->sc_listmap); + bus_dmamem_unmap(sc->sc_dmat, sc->sc_listkva, sc->sc_listnseg); + bus_dmamap_destroy(sc->sc_dmat, sc->sc_listmap); + bus_dmamem_free(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg); ether_ifdetach(ifp); if_detach(ifp); |