From f818612b1bc42a522df976c73da2aabc43faa4b3 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Mon, 24 Jan 2005 20:05:03 +0000 Subject: [PATCH] beacon handling fixups for adhoc mode: o don't reclaim any previous beacon state in ath_beacon_alloc; do it explicitly in ath_newstate o reference count the node held in the beacon frame state block o process ibss merge more intelligently; let the state machine do the right thing instead of explicitly setting the new bssi id o explicitly stop tx dma before doing beacon setup to handle the ibss merge case --- sys/dev/ath/if_ath.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 8af202456849..8c1c3b280ff5 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1710,12 +1710,6 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni) sc->sc_stats.ast_be_nombuf++; /* XXX */ return ENOMEM; /* XXX */ } - if (bf->bf_m != NULL) { - bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); - m_freem(bf->bf_m); - bf->bf_m = NULL; - bf->bf_node = NULL; - } /* * NB: the beacon data buffer must be 32-bit aligned; * we assume the mbuf routines will return us something @@ -1733,7 +1727,7 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni) BUS_DMA_NOWAIT); if (error == 0) { bf->bf_m = m; - bf->bf_node = ni; /* NB: no held reference */ + bf->bf_node = ieee80211_ref_node(ni); } else { m_freem(m); } @@ -1963,13 +1957,17 @@ ath_beacon_free(struct ath_softc *sc) { struct ath_buf *bf; - STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) + STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) { if (bf->bf_m != NULL) { bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); m_freem(bf->bf_m); bf->bf_m = NULL; + } + if (bf->bf_node != NULL) { + ieee80211_free_node(bf->bf_node); bf->bf_node = NULL; } + } } /* @@ -2452,11 +2450,13 @@ ath_recv_mgmt(struct ieee80211com *ic, struct mbuf *m, * frame before attempting the merge. The 802.11 spec * says the station should change it's bssid to match * the oldest station with the same ssid, where oldest - * is determined by the tsf. + * is determined by the tsf. Note that hardware + * reconfiguration happens through callback to + * ath_newstate as the state machine will be go + * from RUN -> RUN when this happens. */ - if (le64toh(ni->ni_tstamp.tsf) >= tsf && - ieee80211_ibss_merge(ic, ni)) - ath_hal_setassocid(ah, ic->ic_bss->ni_bssid, 0); + if (le64toh(ni->ni_tstamp.tsf) >= tsf) + (void) ieee80211_ibss_merge(ic, ni); } break; } @@ -3929,6 +3929,15 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) */ if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS) { + /* + * Stop any previous beacon DMA. This may be + * necessary, for example, when an ibss merge + * causes reconfiguration; there will be a state + * transition from RUN->RUN that means we may + * be called with beacon transmission active. + */ + ath_hal_stoptxdma(ah, sc->sc_bhalq); + ath_beacon_free(sc); error = ath_beacon_alloc(sc, ni); if (error != 0) goto bad;