diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 132 |
1 files changed, 75 insertions, 57 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 19891e7d49ae..385ba03134ba 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi, qi_be; - int qnum; + struct ath_txq *txq; ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { @@ -38,16 +38,16 @@ int ath_beaconq_config(struct ath_softc *sc) qi.tqi_cwmax = 0; } else { /* Adhoc mode; important thing is to use 2x cwmin. */ - qnum = sc->tx.hwq_map[WME_AC_BE]; - ath9k_hw_get_txq_props(ah, qnum, &qi_be); + 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; qi.tqi_cwmax = qi_be.tqi_cwmax; } if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to update h/w beacon queue parameters\n"); + ath_err(common, + "Unable to update h/w beacon queue parameters\n"); return 0; } else { ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); @@ -103,12 +103,32 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; series[0].Rate = rate; - series[0].ChSel = common->tx_chainmask; + series[0].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[0].Rate); series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, series, 4, 0); } +static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_tx_control txctl; + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.txq = sc->beacon.cabq; + + ath_dbg(common, ATH_DBG_XMIT, + "transmitting CABQ packet, skb: %p\n", skb); + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n"); + dev_kfree_skb_any(skb); + } +} + static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -169,8 +189,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error on beaconing\n"); + ath_err(common, "dma_mapping_error on beaconing\n"); return NULL; } @@ -190,8 +209,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, if (skb && cabq_depth) { if (sc->nvifs > 1) { - ath_print(common, ATH_DBG_BEACON, - "Flushing previous cabq traffic\n"); + ath_dbg(common, ATH_DBG_BEACON, + "Flushing previous cabq traffic\n"); ath_draintxq(sc, cabq, false); } } @@ -263,7 +282,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) /* NB: the beacon data buffer must be 32-bit aligned. */ skb = ieee80211_beacon_get(sc->hw, vif); if (skb == NULL) { - ath_print(common, ATH_DBG_BEACON, "cannot get skb\n"); + ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n"); return -ENOMEM; } @@ -287,10 +306,9 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) tsfadjust = intval * avp->av_bslot / ATH_BCBUF; avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); - ath_print(common, ATH_DBG_BEACON, - "stagger beacons, bslot %d intval " - "%u tsfadjust %llu\n", - avp->av_bslot, intval, (unsigned long long)tsfadjust); + ath_dbg(common, ATH_DBG_BEACON, + "stagger beacons, bslot %d intval %u tsfadjust %llu\n", + avp->av_bslot, intval, (unsigned long long)tsfadjust); ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = avp->tsf_adjust; @@ -304,8 +322,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error on beacon alloc\n"); + ath_err(common, "dma_mapping_error on beacon alloc\n"); return -ENOMEM; } @@ -362,13 +379,13 @@ void ath_beacon_tasklet(unsigned long data) sc->beacon.bmisscnt++; if (sc->beacon.bmisscnt < BSTUCK_THRESH) { - ath_print(common, ATH_DBG_BSTUCK, - "missed %u consecutive beacons\n", - sc->beacon.bmisscnt); + ath_dbg(common, ATH_DBG_BSTUCK, + "missed %u consecutive beacons\n", + sc->beacon.bmisscnt); ath9k_hw_bstuck_nfcal(ah); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { - ath_print(common, ATH_DBG_BSTUCK, - "beacon is officially stuck\n"); + ath_dbg(common, ATH_DBG_BSTUCK, + "beacon is officially stuck\n"); sc->sc_flags |= SC_OP_TSF_RESET; ath_reset(sc, true); } @@ -377,9 +394,9 @@ void ath_beacon_tasklet(unsigned long data) } if (sc->beacon.bmisscnt != 0) { - ath_print(common, ATH_DBG_BSTUCK, - "resume beacon xmit after %u misses\n", - sc->beacon.bmisscnt); + ath_dbg(common, ATH_DBG_BSTUCK, + "resume beacon xmit after %u misses\n", + sc->beacon.bmisscnt); sc->beacon.bmisscnt = 0; } @@ -405,9 +422,9 @@ void ath_beacon_tasklet(unsigned long data) vif = sc->beacon.bslot[slot]; aphy = sc->beacon.bslot_aphy[slot]; - ath_print(common, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu, intval, vif); + ath_dbg(common, ATH_DBG_BEACON, + "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", + slot, tsf, tsftu, intval, vif); bfaddr = 0; if (vif) { @@ -449,8 +466,8 @@ void ath_beacon_tasklet(unsigned long data) * are still pending on the queue. */ if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { - ath_print(common, ATH_DBG_FATAL, - "beacon queue %u did not stop?\n", sc->beacon.beaconq); + ath_err(common, "beacon queue %u did not stop?\n", + sc->beacon.beaconq); } /* NB: cabq traffic should already be queued and primed */ @@ -503,7 +520,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, /* Set the computed AP beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); @@ -536,8 +553,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* No need to configure beacon if we are not associated */ if (!common->curaid) { - ath_print(common, ATH_DBG_BEACON, - "STA is not yet associated..skipping beacon config\n"); + ath_dbg(common, ATH_DBG_BEACON, + "STA is not yet associated..skipping beacon config\n"); return; } @@ -549,8 +566,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, * last beacon we received (which may be none). */ dtimperiod = conf->dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ - dtimperiod = 1; dtimcount = conf->dtim_count; if (dtimcount >= dtimperiod) /* NB: sanity check */ dtimcount = 0; @@ -558,8 +573,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, cfpcount = 0; sleepduration = conf->listen_interval * intval; - if (sleepduration <= 0) - sleepduration = intval; /* * Pull nexttbtt forward to reflect the current @@ -630,23 +643,22 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* TSF out of range threshold fixed at 1 second */ bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; - ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); - ath_print(common, ATH_DBG_BEACON, - "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", - bs.bs_bmissthreshold, bs.bs_sleepduration, - bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); + ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); + ath_dbg(common, ATH_DBG_BEACON, + "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", + bs.bs_bmissthreshold, bs.bs_sleepduration, + bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); /* Set the computed STA beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_hw_set_sta_beacon_timers(ah, &bs); ah->imask |= ATH9K_INT_BMISS; ath9k_hw_set_interrupts(ah, ah->imask); } static void ath_beacon_config_adhoc(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ieee80211_vif *vif) + struct ath_beacon_config *conf) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); @@ -670,9 +682,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, nexttbtt += intval; } while (nexttbtt < tsftu); - ath_print(common, ATH_DBG_BEACON, - "IBSS nexttbtt %u intval %u (%u)\n", - nexttbtt, intval, conf->beacon_interval); + ath_dbg(common, ATH_DBG_BEACON, + "IBSS nexttbtt %u intval %u (%u)\n", + nexttbtt, intval, conf->beacon_interval); /* * In IBSS mode enable the beacon timers but only enable SWBA interrupts @@ -686,7 +698,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, /* Set the computed ADHOC beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); @@ -701,18 +713,17 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) /* Setup the beacon configuration parameters */ if (vif) { struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - iftype = vif->type; - cur_conf->beacon_interval = bss_conf->beacon_int; cur_conf->dtim_period = bss_conf->dtim_period; + } else { + iftype = sc->sc_ah->opmode; + } + cur_conf->listen_interval = 1; cur_conf->dtim_count = 1; cur_conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; - } else { - iftype = sc->sc_ah->opmode; - } /* * It looks like mac80211 may end up using beacon interval of zero in @@ -723,20 +734,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) if (cur_conf->beacon_interval == 0) cur_conf->beacon_interval = 100; + /* + * Some times we dont parse dtim period from mac80211, in that case + * use a default value + */ + if (cur_conf->dtim_period == 0) + cur_conf->dtim_period = 1; + switch (iftype) { case NL80211_IFTYPE_AP: ath_beacon_config_ap(sc, cur_conf); break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: - ath_beacon_config_adhoc(sc, cur_conf, vif); + ath_beacon_config_adhoc(sc, cur_conf); break; case NL80211_IFTYPE_STATION: ath_beacon_config_sta(sc, cur_conf); break; default: - ath_print(common, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Unsupported beaconing mode\n"); return; } |