From ad16f31a1c216e2e6436faf2880f640ffe68d3b3 Mon Sep 17 00:00:00 2001 From: dyoung Date: Tue, 14 Dec 2004 19:53:46 +0000 Subject: [PATCH] In wi_stop, wait for transmit commands to complete. Extract subroutine wi_txcmd_wait from wi_cmd and wi_stop. This stops wi from griping, "wi0: command timed out, cmd=0x10b, arg=0x0", when we down/up the interface. Thanks to Pavel Cahyna for reporting this bug. --- sys/dev/ic/wi.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/sys/dev/ic/wi.c b/sys/dev/ic/wi.c index 83126cae8dac..0e7b8f689393 100644 --- a/sys/dev/ic/wi.c +++ b/sys/dev/ic/wi.c @@ -1,4 +1,4 @@ -/* $NetBSD: wi.c,v 1.192 2004/12/13 17:55:28 dyoung Exp $ */ +/* $NetBSD: wi.c,v 1.193 2004/12/14 19:53:46 dyoung Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -106,7 +106,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.192 2004/12/13 17:55:28 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.193 2004/12/14 19:53:46 dyoung Exp $"); #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */ #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */ @@ -910,6 +910,17 @@ wi_init(struct ifnet *ifp) return error; } +STATIC void +wi_txcmd_wait(struct wi_softc *sc) +{ + KASSERT(sc->sc_txcmds == 1); + if (sc->sc_status & WI_EV_CMD) { + sc->sc_status &= ~WI_EV_CMD; + CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); + } else + (void)wi_cmd_wait(sc, WI_CMD_TX | WI_RECLAIM, 0); +} + STATIC void wi_stop(struct ifnet *ifp, int disable) { @@ -925,6 +936,15 @@ wi_stop(struct ifnet *ifp, int disable) DPRINTF(("wi_stop: disable %d\n", disable)); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); + + /* wait for tx command completion (deassoc, deauth) */ + while (sc->sc_txcmds > 0) { + wi_txcmd_wait(sc); + wi_cmd_intr(sc); + } + + /* TBD wait for deassoc, deauth tx completion? */ + if (!sc->sc_invalid) { CSR_WRITE_2(sc, WI_INT_EN, 0); wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0); @@ -2561,14 +2581,8 @@ wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2) sc->sc_txcmds); } #endif - if (sc->sc_txcmds > 0) { - KASSERT(sc->sc_txcmds == 1); - if (sc->sc_status & WI_EV_CMD) { - sc->sc_status &= ~WI_EV_CMD; - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); - } else - (void)wi_cmd_wait(sc, WI_CMD_TX | WI_RECLAIM, 0); - } + if (sc->sc_txcmds > 0) + wi_txcmd_wait(sc); if ((rc = wi_cmd_start(sc, cmd, val0, val1, val2)) != 0) return rc;