diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-07 19:18:36 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-07 19:18:36 +0000 |
commit | 8d9f5ecf4a86447e7816c3fd1496210810afe1e5 (patch) | |
tree | 7ec3ade10adfa19732b595c941958db4cee252cf /sys | |
parent | 9866ed90cfff90a04c7a70dd75d2118ed6a44f95 (diff) |
After we wait for the MAC's transmit section to idle, drain the
transmit queue and cancel the watchdog timer. Fixes the annoying
"atw0: transmit timeout" messages. From NetBSD (dyoung)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/atw.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/sys/dev/ic/atw.c b/sys/dev/ic/atw.c index d9666960549..63797f5f756 100644 --- a/sys/dev/ic/atw.c +++ b/sys/dev/ic/atw.c @@ -1,5 +1,5 @@ -/* $OpenBSD: atw.c,v 1.3 2004/07/07 19:11:27 millert Exp $ */ -/* $NetBSD: atw.c,v 1.35 2004/06/23 09:05:50 dyoung Exp $ */ +/* $OpenBSD: atw.c,v 1.4 2004/07/07 19:18:35 millert Exp $ */ +/* $NetBSD: atw.c,v 1.36 2004/06/23 09:27:59 dyoung Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ #include <sys/cdefs.h> #if defined(__NetBSD__) -__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.35 2004/06/23 09:05:50 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.36 2004/06/23 09:27:59 dyoung Exp $"); #endif #include "bpfilter.h" @@ -190,6 +190,7 @@ void atw_start(struct ifnet *); void atw_watchdog(struct ifnet *); int atw_ioctl(struct ifnet *, u_long, caddr_t); int atw_init(struct ifnet *); +void atw_txdrain(struct atw_softc *); void atw_stop(struct ifnet *, int); void atw_reset(struct atw_softc *); @@ -2511,6 +2512,26 @@ atw_add_rxbuf(struct atw_softc *sc, int idx) } /* + * Release any queued transmit buffers. + */ +void +atw_txdrain(struct atw_softc *sc) +{ + struct atw_txsoft *txs; + + while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); + if (txs->txs_mbuf != NULL) { + bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); + m_freem(txs->txs_mbuf); + txs->txs_mbuf = NULL; + } + SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); + } + sc->sc_tx_timer = 0; +} + +/* * atw_stop: [ ifnet interface function ] * * Stop transmission on the interface. @@ -2520,7 +2541,6 @@ atw_stop(struct ifnet *ifp, int disable) { struct atw_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - struct atw_txsoft *txs; ieee80211_new_state(ic, IEEE80211_S_INIT, -1); @@ -2534,18 +2554,7 @@ atw_stop(struct ifnet *ifp, int disable) ATW_WRITE(sc, ATW_TDBP, 0); ATW_WRITE(sc, ATW_RDB, 0); - /* - * Release any queued transmit buffers. - */ - while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); - if (txs->txs_mbuf != NULL) { - bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); - m_freem(txs->txs_mbuf); - txs->txs_mbuf = NULL; - } - SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); - } + atw_txdrain(sc); if (disable) { atw_rxdrain(sc); @@ -2558,8 +2567,7 @@ atw_stop(struct ifnet *ifp, int disable) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ifp->if_timer = 0; - /* XXX */ - if (ATW_IS_ENABLED(sc)) + if (!disable) atw_reset(sc); } @@ -2883,6 +2891,7 @@ atw_idle(struct atw_softc *sc, u_int32_t bits) sc->sc_dev.dv_xname, bits, test0, stsr)); } out: + atw_txdrain(sc); splx(s); return; } |