diff options
author | sam <sam@FreeBSD.org> | 2005-01-24 20:05:03 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2005-01-24 20:05:03 +0000 |
commit | b6d4f1528e4c8f79bf33f2ecb27f35b2b8ed0344 (patch) | |
tree | 12d11bcc5689d7b4c98288e207942b67ac663c61 /sys/dev/ath/if_ath.c | |
parent | a50641e90c053220b37295efc785e0c4b427213b (diff) | |
download | FreeBSD-src-b6d4f1528e4c8f79bf33f2ecb27f35b2b8ed0344.zip FreeBSD-src-b6d4f1528e4c8f79bf33f2ecb27f35b2b8ed0344.tar.gz |
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
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 8af2024..8c1c3b2 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; |