summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2006-02-18 09:41:42 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2006-02-18 09:41:42 +0000
commitf8780eb937d7ccc6465fb22612ddf0b181faeb1b (patch)
treea50b5d4c1849de98112886646a84f20cfc6c78dc /sys/dev
parent954dcf99413d4bfc6c613247eb1415478a5a0a11 (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.c33
-rw-r--r--sys/dev/ic/rt2661.c31
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;