diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 626418222c85..40775da8941e 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -48,7 +48,10 @@ int ath_beaconq_config(struct ath_softc *sc) txq = sc->tx.txq_map[WME_AC_BE]; ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; - qi.tqi_cwmin = 4*qi_be.tqi_cwmin; + if (ah->slottime == ATH9K_SLOT_TIME_20) + qi.tqi_cwmin = 2*qi_be.tqi_cwmin; + else + qi.tqi_cwmin = 4*qi_be.tqi_cwmin; qi.tqi_cwmax = qi_be.tqi_cwmax; } @@ -91,7 +94,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, info.txpower = MAX_RATE_POWER; info.keyix = ATH9K_TXKEYIX_INVALID; info.keytype = ATH9K_KEY_TYPE_CLEAR; - info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ; + info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK; info.buf_addr[0] = bf->bf_buf_addr; info.buf_len[0] = roundup(skb->len, 4); @@ -359,6 +362,11 @@ void ath_beacon_tasklet(unsigned long data) int slot; u32 bfaddr, bc = 0; + if (work_pending(&sc->hw_reset_work)) { + ath_dbg(common, RESET, + "reset work is pending, skip beaconing now\n"); + return; + } /* * Check if the previous beacon has gone out. If * not don't try to post another, skip this period @@ -369,6 +377,9 @@ void ath_beacon_tasklet(unsigned long data) if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { sc->beacon.bmisscnt++; + if (!ath9k_hw_check_alive(ah)) + ieee80211_queue_work(sc->hw, &sc->hw_check_work); + if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { ath_dbg(common, BSTUCK, "missed %u consecutive beacons\n", @@ -378,7 +389,8 @@ void ath_beacon_tasklet(unsigned long data) ath9k_hw_bstuck_nfcal(ah); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); - sc->sc_flags |= SC_OP_TSF_RESET; + sc->beacon.bmisscnt = 0; + set_bit(SC_OP_TSF_RESET, &sc->sc_flags); ieee80211_queue_work(sc->hw, &sc->hw_reset_work); } @@ -468,16 +480,16 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 next_beacon, u32 beacon_period) { - if (sc->sc_flags & SC_OP_TSF_RESET) { + if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) { ath9k_ps_wakeup(sc); ath9k_hw_reset_tsf(sc->sc_ah); } ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); - if (sc->sc_flags & SC_OP_TSF_RESET) { + if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) { ath9k_ps_restore(sc); - sc->sc_flags &= ~SC_OP_TSF_RESET; + clear_bit(SC_OP_TSF_RESET, &sc->sc_flags); } } @@ -507,7 +519,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, /* Set the computed AP beacon timers */ ath9k_hw_disable_interrupts(ah); - sc->sc_flags |= SC_OP_TSF_RESET; + set_bit(SC_OP_TSF_RESET, &sc->sc_flags); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah); @@ -650,6 +662,8 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, u32 tsf, intval, nexttbtt; ath9k_reset_beacon_status(sc); + if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) + ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp); intval = TU_TO_USEC(conf->beacon_interval); tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval); @@ -713,7 +727,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc, */ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && (vif->type == NL80211_IFTYPE_STATION) && - (sc->sc_flags & SC_OP_BEACONS) && + test_bit(SC_OP_BEACONS, &sc->sc_flags) && !avp->primary_sta_vif) { ath_dbg(common, CONFIG, "Beacon already configured for a station interface\n"); @@ -799,15 +813,17 @@ void ath_set_beacon(struct ath_softc *sc) return; } - sc->sc_flags |= SC_OP_BEACONS; + set_bit(SC_OP_BEACONS, &sc->sc_flags); } void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) { struct ath_hw *ah = sc->sc_ah; - if (!ath_has_valid_bslot(sc)) + if (!ath_has_valid_bslot(sc)) { + clear_bit(SC_OP_BEACONS, &sc->sc_flags); return; + } ath9k_ps_wakeup(sc); if (status) { |