diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2006-02-18 09:41:42 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2006-02-18 09:41:42 +0000 |
commit | f8780eb937d7ccc6465fb22612ddf0b181faeb1b (patch) | |
tree | a50b5d4c1849de98112886646a84f20cfc6c78dc /sys/dev | |
parent | 954dcf99413d4bfc6c613247eb1415478a5a0a11 (diff) |
don't try to release references to nodes that have been freed by net80211.
in HostAP mode, when switching to the INIT state, net80211 sends a DISASSOC
and a DEAUTH frame to all associated stations and immediately free all the
nodes while we may still hold references to them in our Tx queues.
hopefully, this should fix PRs 4469/kernel and 4953/kernel.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/rt2560.c | 33 | ||||
-rw-r--r-- | sys/dev/ic/rt2661.c | 31 |
2 files changed, 41 insertions, 23 deletions
diff --git a/sys/dev/ic/rt2560.c b/sys/dev/ic/rt2560.c index f829af55070..547e71047aa 100644 --- a/sys/dev/ic/rt2560.c +++ b/sys/dev/ic/rt2560.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2560.c,v 1.10 2006/01/14 12:43:27 damien Exp $ */ +/* $OpenBSD: rt2560.c,v 1.11 2006/02/18 09:41:41 damien Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -494,7 +494,7 @@ rt2560_detach(void *xsc) timeout_del(&sc->scan_ch); timeout_del(&sc->rssadapt_ch); - ieee80211_ifdetach(ifp); + ieee80211_ifdetach(ifp); /* free all nodes */ if_detach(ifp); rt2560_free_tx_ring(sc, &sc->txq); @@ -583,7 +583,6 @@ fail: rt2560_free_tx_ring(sc, ring); void rt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) { - struct ieee80211com *ic = &sc->sc_ic; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; int i; @@ -600,10 +599,11 @@ rt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) data->m = NULL; } - if (data->ni != NULL) { - ieee80211_release_node(ic, data->ni); - data->ni = NULL; - } + /* + * The node has already been freed at that point so don't call + * ieee80211_release_node() here. + */ + data->ni = NULL; desc->flags = 0; } @@ -619,7 +619,6 @@ rt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) void rt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) { - struct ieee80211com *ic = &sc->sc_ic; struct rt2560_tx_data *data; int i; @@ -644,8 +643,11 @@ rt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) m_freem(data->m); } - if (data->ni != NULL) - ieee80211_release_node(ic, data->ni); + /* + * The node has already been freed at that point so + * don't call ieee80211_release_node() here. + */ + data->ni = NULL; if (data->map != NULL) bus_dmamap_destroy(sc->sc_dmat, data->map); @@ -2069,6 +2071,13 @@ rt2560_start(struct ifnet *ifp) struct mbuf *m0; struct ieee80211_node *ni; + /* + * net80211 may still try to send management frames even if the + * IFF_RUNNING flag is not set... + */ + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + return; + for (;;) { IF_POLL(&ic->ic_mgtq, m0); if (m0 != NULL) { @@ -2822,12 +2831,12 @@ rt2560_stop(struct ifnet *ifp, int disable) struct rt2560_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - sc->sc_tx_timer = 0; ifp->if_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */ + /* abort Tx */ RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX); diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c index 56ca6572e79..24779315ae8 100644 --- a/sys/dev/ic/rt2661.c +++ b/sys/dev/ic/rt2661.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661.c,v 1.9 2006/02/15 17:23:26 damien Exp $ */ +/* $OpenBSD: rt2661.c,v 1.10 2006/02/18 09:41:41 damien Exp $ */ /*- * Copyright (c) 2006 @@ -508,7 +508,7 @@ rt2661_detach(void *xsc) timeout_del(&sc->scan_ch); timeout_del(&sc->rssadapt_ch); - ieee80211_ifdetach(ifp); + ieee80211_ifdetach(ifp); /* free all nodes */ if_detach(ifp); rt2661_free_tx_ring(sc, &sc->txq[0]); @@ -597,7 +597,6 @@ fail: rt2661_free_tx_ring(sc, ring); void rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) { - struct ieee80211com *ic = &sc->sc_ic; struct rt2661_tx_desc *desc; struct rt2661_tx_data *data; int i; @@ -614,10 +613,11 @@ rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) data->m = NULL; } - if (data->ni != NULL) { - ieee80211_release_node(ic, data->ni); - data->ni = NULL; - } + /* + * The node has already been freed at that point so don't call + * ieee80211_release_node() here. + */ + data->ni = NULL; desc->flags = 0; } @@ -632,7 +632,6 @@ rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) void rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) { - struct ieee80211com *ic = &sc->sc_ic; struct rt2661_tx_data *data; int i; @@ -657,8 +656,11 @@ rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) m_freem(data->m); } - if (data->ni != NULL) - ieee80211_release_node(ic, data->ni); + /* + * The node has already been freed at that point so + * don't call ieee80211_release_node() here. + */ + data->ni = NULL; if (data->map != NULL) bus_dmamap_destroy(sc->sc_dmat, data->map); @@ -1895,6 +1897,13 @@ rt2661_start(struct ifnet *ifp) struct mbuf *m0; struct ieee80211_node *ni; + /* + * net80211 may still try to send management frames even if the + * IFF_RUNNING flag is not set... + */ + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + return; + for (;;) { IF_POLL(&ic->ic_mgtq, m0); if (m0 != NULL) { @@ -2693,7 +2702,7 @@ rt2661_stop(struct ifnet *ifp, int disable) struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); + ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */ sc->sc_tx_timer = 0; ifp->if_timer = 0; |