From c42082fe656a7deeb573d8120c2cf28dcc4313e0 Mon Sep 17 00:00:00 2001 From: Damien Bergamini Date: Sun, 19 Feb 2006 08:44:18 +0000 Subject: sync w/ rt2560.c: 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. --- sys/dev/usb/if_ral.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'sys/dev/usb') diff --git a/sys/dev/usb/if_ral.c b/sys/dev/usb/if_ral.c index 587fb56cdb9..9eabe32b4e5 100644 --- a/sys/dev/usb/if_ral.c +++ b/sys/dev/usb/if_ral.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ral.c,v 1.64 2006/02/11 09:31:42 damien Exp $ */ +/* $OpenBSD: if_ral.c,v 1.65 2006/02/19 08:44:17 damien Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -527,6 +527,9 @@ USB_DETACH(ural) s = splusb(); + ieee80211_ifdetach(ifp); /* free all nodes */ + if_detach(ifp); + usb_rem_task(sc->sc_udev, &sc->sc_task); timeout_del(&sc->scan_ch); timeout_del(&sc->amrr_ch); @@ -549,9 +552,6 @@ USB_DETACH(ural) ural_free_rx_list(sc); ural_free_tx_list(sc); - ieee80211_ifdetach(ifp); - if_detach(ifp); - splx(s); usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, @@ -600,7 +600,6 @@ fail: ural_free_tx_list(sc); Static void ural_free_tx_list(struct ural_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; struct ural_tx_data *data; int i; @@ -612,10 +611,11 @@ ural_free_tx_list(struct ural_softc *sc) data->xfer = 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; } } @@ -1400,6 +1400,13 @@ ural_start(struct ifnet *ifp) struct ieee80211_node *ni; struct mbuf *m0; + /* + * 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) { @@ -2249,7 +2256,11 @@ ural_stop(struct ifnet *ifp, int disable) struct ural_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 */ /* disable Rx */ ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); @@ -2258,10 +2269,6 @@ ural_stop(struct ifnet *ifp, int disable) ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP); ural_write(sc, RAL_MAC_CSR1, 0); - sc->sc_tx_timer = 0; - ifp->if_timer = 0; - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - if (sc->amrr_xfer != NULL) { usbd_free_xfer(sc->amrr_xfer); sc->amrr_xfer = NULL; -- cgit v1.2.3