X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fath%2Fath9k%2Fbeacon.c;h=77face76e05f396b9f68785bf0832cdf991b806f;hb=774610e4f26cb3d9da14a8b5974324c9e51017bd;hp=1660ef17aaf5479215171bcc7211028a1bae4db6;hpb=94db29368a658b13a088db87c7b0bf59b1a7492d;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 1660ef1..77face7 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -62,7 +62,7 @@ int ath_beaconq_config(struct ath_softc *sc) * Beacons are always sent out at the lowest rate, and are not retried. */ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, - struct ath_buf *bf) + struct ath_buf *bf, int rateidx) { struct sk_buff *skb = bf->bf_mpdu; struct ath_hw *ah = sc->sc_ah; @@ -93,12 +93,10 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); } - ds->ds_data = bf->bf_buf_addr; - sband = &sc->sbands[common->hw->conf.channel->band]; - rate = sband->bitrates[0].hw_value; + rate = sband->bitrates[rateidx].hw_value; if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - rate |= sband->bitrates[0].hw_value_short; + rate |= sband->bitrates[rateidx].hw_value_short; ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, ATH9K_PKT_TYPE_BEACON, @@ -109,7 +107,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, /* NB: beacon's BufLen must be a multiple of 4 bytes */ ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), - true, true, ds); + true, true, ds, bf->bf_buf_addr, + sc->beacon.beaconq); memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; @@ -206,7 +205,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, } } - ath_beacon_setup(sc, avp, bf); + ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx); while (skb) { ath_tx_cabq(hw, skb); @@ -237,7 +236,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, bf = avp->av_bcbuf; skb = bf->bf_mpdu; - ath_beacon_setup(sc, avp, bf); + ath_beacon_setup(sc, avp, bf, 0); /* NB: caller is known to have already stopped tx dma */ ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); @@ -275,17 +274,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) avp->av_bslot = 0; for (slot = 0; slot < ATH_BCBUF; slot++) if (sc->beacon.bslot[slot] == NULL) { - /* - * XXX hack, space out slots to better - * deal with misses - */ - if (slot+1 < ATH_BCBUF && - sc->beacon.bslot[slot+1] == NULL) { - avp->av_bslot = slot+1; - break; - } avp->av_bslot = slot; + /* NB: keep looking for a double slot */ + if (slot == 0 || !sc->beacon.bslot[slot-1]) + break; } BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); sc->beacon.bslot[avp->av_bslot] = vif; @@ -480,7 +473,8 @@ void ath_beacon_tasklet(unsigned long data) sc->beacon.updateslot = COMMIT; /* commit next beacon */ sc->beacon.slotupdate = slot; } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { - ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); + ah->slottime = sc->beacon.slottime; + ath9k_hw_init_global_settings(ah); sc->beacon.updateslot = OK; } if (bfaddr != 0) { @@ -523,33 +517,31 @@ static void ath9k_beacon_init(struct ath_softc *sc, static void ath_beacon_config_ap(struct ath_softc *sc, struct ath_beacon_config *conf) { + struct ath_hw *ah = sc->sc_ah; u32 nexttbtt, intval; - /* Configure the timers only when the TSF has to be reset */ - - if (!(sc->sc_flags & SC_OP_TSF_RESET)) - return; - /* NB: the beacon interval is kept internally in TU's */ intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; intval /= ATH_BCBUF; /* for staggered beacons */ nexttbtt = intval; - intval |= ATH9K_BEACON_RESET_TSF; + + if (sc->sc_flags & SC_OP_TSF_RESET) + intval |= ATH9K_BEACON_RESET_TSF; /* * In AP mode we enable the beacon timers and SWBA interrupts to * prepare beacon frames. */ intval |= ATH9K_BEACON_ENA; - sc->imask |= ATH9K_INT_SWBA; + ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); /* Set the computed AP beacon timers */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_set_interrupts(ah, 0); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); /* Clear the reset TSF flag, so that subsequent beacon updation will not reset the HW TSF. */ @@ -568,7 +560,8 @@ static void ath_beacon_config_ap(struct ath_softc *sc, static void ath_beacon_config_sta(struct ath_softc *sc, struct ath_beacon_config *conf) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ath9k_beacon_state bs; int dtimperiod, dtimcount, sleepduration; int cfpperiod, cfpcount; @@ -576,6 +569,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc, u64 tsf; int num_beacons, offset, dtim_dec_count, cfp_dec_count; + /* 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"); + return; + } + memset(&bs, 0, sizeof(bs)); intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; @@ -600,7 +600,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc, * Pull nexttbtt forward to reflect the current * TSF and calculate dtim+cfp state for the result. */ - tsf = ath9k_hw_gettsf64(sc->sc_ah); + tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; num_beacons = tsftu / intval + 1; @@ -673,17 +673,18 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* Set the computed STA beacon timers */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); - sc->imask |= ATH9K_INT_BMISS; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, 0); + 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_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); u64 tsf; u32 tsftu, intval, nexttbtt; @@ -698,7 +699,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, else if (intval) nexttbtt = roundup(nexttbtt, intval); - tsf = ath9k_hw_gettsf64(sc->sc_ah); + tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; do { nexttbtt += intval; @@ -714,20 +715,20 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, * self-linked tx descriptor and let the hardware deal with things. */ intval |= ATH9K_BEACON_ENA; - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) - sc->imask |= ATH9K_INT_SWBA; + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) + ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); /* Set the computed ADHOC beacon timers */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_set_interrupts(ah, 0); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); /* FIXME: Handle properly when vif is NULL */ - if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) + if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) ath_beacon_start_adhoc(sc, vif); } @@ -738,7 +739,6 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) enum nl80211_iftype iftype; /* Setup the beacon configuration parameters */ - if (vif) { struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;