diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index fcb36ab..a4bdfdb 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -143,7 +143,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, avp = (void *)vif->drv_priv; cabq = sc->beacon.cabq; - if (avp->av_bcbuf == NULL) + if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active) return NULL; /* Release the old beacon first */ @@ -226,6 +226,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) struct ath_vif *avp; struct ath_buf *bf; struct sk_buff *skb; + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; __le64 tstamp; avp = (void *)vif->drv_priv; @@ -248,6 +249,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) for (slot = 0; slot < ATH_BCBUF; slot++) if (sc->beacon.bslot[slot] == NULL) { avp->av_bslot = slot; + avp->is_bslot_active = false; /* NB: keep looking for a double slot */ if (slot == 0 || !sc->beacon.bslot[slot-1]) @@ -282,7 +284,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) u64 tsfadjust; int intval; - intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; + intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; /* * Calculate the TSF offset for this beacon slot, i.e., the @@ -314,6 +316,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) ath_err(common, "dma_mapping_error on beacon alloc\n"); return -ENOMEM; } + avp->is_bslot_active = true; return 0; } @@ -346,6 +349,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) void ath_beacon_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath_buf *bf = NULL; @@ -393,7 +397,7 @@ void ath_beacon_tasklet(unsigned long data) * on the tsf to safeguard against missing an swba. */ - intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; + intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf); @@ -747,3 +751,36 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) sc->sc_flags |= SC_OP_BEACONS; } + +void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_vif *avp; + int slot; + bool found = false; + + ath9k_ps_wakeup(sc); + if (status) { + for (slot = 0; slot < ATH_BCBUF; slot++) { + if (sc->beacon.bslot[slot]) { + avp = (void *)sc->beacon.bslot[slot]->drv_priv; + if (avp->is_bslot_active) { + found = true; + break; + } + } + } + if (found) { + /* Re-enable beaconing */ + ah->imask |= ATH9K_INT_SWBA; + ath9k_hw_set_interrupts(ah, ah->imask); + } + } else { + /* Disable SWBA interrupt */ + ah->imask &= ~ATH9K_INT_SWBA; + ath9k_hw_set_interrupts(ah, ah->imask); + tasklet_kill(&sc->bcon_tasklet); + ath9k_hw_stoptxdma(ah, sc->beacon.beaconq); + } + ath9k_ps_restore(sc); +} |