diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/ath/ath9k/beacon.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 162 |
1 files changed, 91 insertions, 71 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 45c4ea57616b..b4a31a43a62c 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -23,10 +23,12 @@ | |||
23 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS | 23 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS |
24 | * settings and channel width min/max | 24 | * settings and channel width min/max |
25 | */ | 25 | */ |
26 | static int ath_beaconq_config(struct ath_softc *sc) | 26 | int ath_beaconq_config(struct ath_softc *sc) |
27 | { | 27 | { |
28 | struct ath_hw *ah = sc->sc_ah; | 28 | struct ath_hw *ah = sc->sc_ah; |
29 | struct ath9k_tx_queue_info qi; | 29 | struct ath_common *common = ath9k_hw_common(ah); |
30 | struct ath9k_tx_queue_info qi, qi_be; | ||
31 | int qnum; | ||
30 | 32 | ||
31 | ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); | 33 | ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); |
32 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { | 34 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { |
@@ -36,14 +38,17 @@ static int ath_beaconq_config(struct ath_softc *sc) | |||
36 | qi.tqi_cwmax = 0; | 38 | qi.tqi_cwmax = 0; |
37 | } else { | 39 | } else { |
38 | /* Adhoc mode; important thing is to use 2x cwmin. */ | 40 | /* Adhoc mode; important thing is to use 2x cwmin. */ |
39 | qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs; | 41 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, |
40 | qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin; | 42 | ATH9K_WME_AC_BE); |
41 | qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax; | 43 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); |
44 | qi.tqi_aifs = qi_be.tqi_aifs; | ||
45 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | ||
46 | qi.tqi_cwmax = qi_be.tqi_cwmax; | ||
42 | } | 47 | } |
43 | 48 | ||
44 | if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { | 49 | if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { |
45 | DPRINTF(sc, ATH_DBG_FATAL, | 50 | ath_print(common, ATH_DBG_FATAL, |
46 | "Unable to update h/w beacon queue parameters\n"); | 51 | "Unable to update h/w beacon queue parameters\n"); |
47 | return 0; | 52 | return 0; |
48 | } else { | 53 | } else { |
49 | ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); | 54 | ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); |
@@ -57,15 +62,16 @@ static int ath_beaconq_config(struct ath_softc *sc) | |||
57 | * Beacons are always sent out at the lowest rate, and are not retried. | 62 | * Beacons are always sent out at the lowest rate, and are not retried. |
58 | */ | 63 | */ |
59 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | 64 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, |
60 | struct ath_buf *bf) | 65 | struct ath_buf *bf, int rateidx) |
61 | { | 66 | { |
62 | struct sk_buff *skb = bf->bf_mpdu; | 67 | struct sk_buff *skb = bf->bf_mpdu; |
63 | struct ath_hw *ah = sc->sc_ah; | 68 | struct ath_hw *ah = sc->sc_ah; |
69 | struct ath_common *common = ath9k_hw_common(ah); | ||
64 | struct ath_desc *ds; | 70 | struct ath_desc *ds; |
65 | struct ath9k_11n_rate_series series[4]; | 71 | struct ath9k_11n_rate_series series[4]; |
66 | const struct ath_rate_table *rt; | ||
67 | int flags, antenna, ctsrate = 0, ctsduration = 0; | 72 | int flags, antenna, ctsrate = 0, ctsduration = 0; |
68 | u8 rate; | 73 | struct ieee80211_supported_band *sband; |
74 | u8 rate = 0; | ||
69 | 75 | ||
70 | ds = bf->bf_desc; | 76 | ds = bf->bf_desc; |
71 | flags = ATH9K_TXDESC_NOACK; | 77 | flags = ATH9K_TXDESC_NOACK; |
@@ -89,10 +95,10 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
89 | 95 | ||
90 | ds->ds_data = bf->bf_buf_addr; | 96 | ds->ds_data = bf->bf_buf_addr; |
91 | 97 | ||
92 | rt = sc->cur_rate_table; | 98 | sband = &sc->sbands[common->hw->conf.channel->band]; |
93 | rate = rt->info[0].ratecode; | 99 | rate = sband->bitrates[rateidx].hw_value; |
94 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) | 100 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) |
95 | rate |= rt->info[0].short_preamble; | 101 | rate |= sband->bitrates[rateidx].hw_value_short; |
96 | 102 | ||
97 | ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, | 103 | ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, |
98 | ATH9K_PKT_TYPE_BEACON, | 104 | ATH9K_PKT_TYPE_BEACON, |
@@ -108,7 +114,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
108 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 114 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
109 | series[0].Tries = 1; | 115 | series[0].Tries = 1; |
110 | series[0].Rate = rate; | 116 | series[0].Rate = rate; |
111 | series[0].ChSel = sc->tx_chainmask; | 117 | series[0].ChSel = common->tx_chainmask; |
112 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | 118 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; |
113 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, | 119 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, |
114 | series, 4, 0); | 120 | series, 4, 0); |
@@ -119,6 +125,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
119 | { | 125 | { |
120 | struct ath_wiphy *aphy = hw->priv; | 126 | struct ath_wiphy *aphy = hw->priv; |
121 | struct ath_softc *sc = aphy->sc; | 127 | struct ath_softc *sc = aphy->sc; |
128 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
122 | struct ath_buf *bf; | 129 | struct ath_buf *bf; |
123 | struct ath_vif *avp; | 130 | struct ath_vif *avp; |
124 | struct sk_buff *skb; | 131 | struct sk_buff *skb; |
@@ -172,7 +179,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
172 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 179 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
173 | dev_kfree_skb_any(skb); | 180 | dev_kfree_skb_any(skb); |
174 | bf->bf_mpdu = NULL; | 181 | bf->bf_mpdu = NULL; |
175 | DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n"); | 182 | ath_print(common, ATH_DBG_FATAL, |
183 | "dma_mapping_error on beaconing\n"); | ||
176 | return NULL; | 184 | return NULL; |
177 | } | 185 | } |
178 | 186 | ||
@@ -192,13 +200,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
192 | 200 | ||
193 | if (skb && cabq_depth) { | 201 | if (skb && cabq_depth) { |
194 | if (sc->nvifs > 1) { | 202 | if (sc->nvifs > 1) { |
195 | DPRINTF(sc, ATH_DBG_BEACON, | 203 | ath_print(common, ATH_DBG_BEACON, |
196 | "Flushing previous cabq traffic\n"); | 204 | "Flushing previous cabq traffic\n"); |
197 | ath_draintxq(sc, cabq, false); | 205 | ath_draintxq(sc, cabq, false); |
198 | } | 206 | } |
199 | } | 207 | } |
200 | 208 | ||
201 | ath_beacon_setup(sc, avp, bf); | 209 | ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx); |
202 | 210 | ||
203 | while (skb) { | 211 | while (skb) { |
204 | ath_tx_cabq(hw, skb); | 212 | ath_tx_cabq(hw, skb); |
@@ -216,6 +224,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, | |||
216 | struct ieee80211_vif *vif) | 224 | struct ieee80211_vif *vif) |
217 | { | 225 | { |
218 | struct ath_hw *ah = sc->sc_ah; | 226 | struct ath_hw *ah = sc->sc_ah; |
227 | struct ath_common *common = ath9k_hw_common(ah); | ||
219 | struct ath_buf *bf; | 228 | struct ath_buf *bf; |
220 | struct ath_vif *avp; | 229 | struct ath_vif *avp; |
221 | struct sk_buff *skb; | 230 | struct sk_buff *skb; |
@@ -228,30 +237,19 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, | |||
228 | bf = avp->av_bcbuf; | 237 | bf = avp->av_bcbuf; |
229 | skb = bf->bf_mpdu; | 238 | skb = bf->bf_mpdu; |
230 | 239 | ||
231 | ath_beacon_setup(sc, avp, bf); | 240 | ath_beacon_setup(sc, avp, bf, 0); |
232 | 241 | ||
233 | /* NB: caller is known to have already stopped tx dma */ | 242 | /* NB: caller is known to have already stopped tx dma */ |
234 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); | 243 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); |
235 | ath9k_hw_txstart(ah, sc->beacon.beaconq); | 244 | ath9k_hw_txstart(ah, sc->beacon.beaconq); |
236 | DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", | 245 | ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", |
237 | sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); | 246 | sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); |
238 | } | ||
239 | |||
240 | int ath_beaconq_setup(struct ath_hw *ah) | ||
241 | { | ||
242 | struct ath9k_tx_queue_info qi; | ||
243 | |||
244 | memset(&qi, 0, sizeof(qi)); | ||
245 | qi.tqi_aifs = 1; | ||
246 | qi.tqi_cwmin = 0; | ||
247 | qi.tqi_cwmax = 0; | ||
248 | /* NB: don't enable any interrupts */ | ||
249 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | ||
250 | } | 247 | } |
251 | 248 | ||
252 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | 249 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) |
253 | { | 250 | { |
254 | struct ath_softc *sc = aphy->sc; | 251 | struct ath_softc *sc = aphy->sc; |
252 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
255 | struct ath_vif *avp; | 253 | struct ath_vif *avp; |
256 | struct ath_buf *bf; | 254 | struct ath_buf *bf; |
257 | struct sk_buff *skb; | 255 | struct sk_buff *skb; |
@@ -309,7 +307,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
309 | /* NB: the beacon data buffer must be 32-bit aligned. */ | 307 | /* NB: the beacon data buffer must be 32-bit aligned. */ |
310 | skb = ieee80211_beacon_get(sc->hw, vif); | 308 | skb = ieee80211_beacon_get(sc->hw, vif); |
311 | if (skb == NULL) { | 309 | if (skb == NULL) { |
312 | DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n"); | 310 | ath_print(common, ATH_DBG_BEACON, "cannot get skb\n"); |
313 | return -ENOMEM; | 311 | return -ENOMEM; |
314 | } | 312 | } |
315 | 313 | ||
@@ -333,9 +331,10 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
333 | tsfadjust = intval * avp->av_bslot / ATH_BCBUF; | 331 | tsfadjust = intval * avp->av_bslot / ATH_BCBUF; |
334 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); | 332 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); |
335 | 333 | ||
336 | DPRINTF(sc, ATH_DBG_BEACON, | 334 | ath_print(common, ATH_DBG_BEACON, |
337 | "stagger beacons, bslot %d intval %u tsfadjust %llu\n", | 335 | "stagger beacons, bslot %d intval " |
338 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | 336 | "%u tsfadjust %llu\n", |
337 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | ||
339 | 338 | ||
340 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = | 339 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = |
341 | avp->tsf_adjust; | 340 | avp->tsf_adjust; |
@@ -349,8 +348,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
349 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 348 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
350 | dev_kfree_skb_any(skb); | 349 | dev_kfree_skb_any(skb); |
351 | bf->bf_mpdu = NULL; | 350 | bf->bf_mpdu = NULL; |
352 | DPRINTF(sc, ATH_DBG_FATAL, | 351 | ath_print(common, ATH_DBG_FATAL, |
353 | "dma_mapping_error on beacon alloc\n"); | 352 | "dma_mapping_error on beacon alloc\n"); |
354 | return -ENOMEM; | 353 | return -ENOMEM; |
355 | } | 354 | } |
356 | 355 | ||
@@ -386,6 +385,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
386 | { | 385 | { |
387 | struct ath_softc *sc = (struct ath_softc *)data; | 386 | struct ath_softc *sc = (struct ath_softc *)data; |
388 | struct ath_hw *ah = sc->sc_ah; | 387 | struct ath_hw *ah = sc->sc_ah; |
388 | struct ath_common *common = ath9k_hw_common(ah); | ||
389 | struct ath_buf *bf = NULL; | 389 | struct ath_buf *bf = NULL; |
390 | struct ieee80211_vif *vif; | 390 | struct ieee80211_vif *vif; |
391 | struct ath_wiphy *aphy; | 391 | struct ath_wiphy *aphy; |
@@ -405,12 +405,12 @@ void ath_beacon_tasklet(unsigned long data) | |||
405 | sc->beacon.bmisscnt++; | 405 | sc->beacon.bmisscnt++; |
406 | 406 | ||
407 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { | 407 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { |
408 | DPRINTF(sc, ATH_DBG_BEACON, | 408 | ath_print(common, ATH_DBG_BEACON, |
409 | "missed %u consecutive beacons\n", | 409 | "missed %u consecutive beacons\n", |
410 | sc->beacon.bmisscnt); | 410 | sc->beacon.bmisscnt); |
411 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 411 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
412 | DPRINTF(sc, ATH_DBG_BEACON, | 412 | ath_print(common, ATH_DBG_BEACON, |
413 | "beacon is officially stuck\n"); | 413 | "beacon is officially stuck\n"); |
414 | sc->sc_flags |= SC_OP_TSF_RESET; | 414 | sc->sc_flags |= SC_OP_TSF_RESET; |
415 | ath_reset(sc, false); | 415 | ath_reset(sc, false); |
416 | } | 416 | } |
@@ -419,9 +419,9 @@ void ath_beacon_tasklet(unsigned long data) | |||
419 | } | 419 | } |
420 | 420 | ||
421 | if (sc->beacon.bmisscnt != 0) { | 421 | if (sc->beacon.bmisscnt != 0) { |
422 | DPRINTF(sc, ATH_DBG_BEACON, | 422 | ath_print(common, ATH_DBG_BEACON, |
423 | "resume beacon xmit after %u misses\n", | 423 | "resume beacon xmit after %u misses\n", |
424 | sc->beacon.bmisscnt); | 424 | sc->beacon.bmisscnt); |
425 | sc->beacon.bmisscnt = 0; | 425 | sc->beacon.bmisscnt = 0; |
426 | } | 426 | } |
427 | 427 | ||
@@ -447,9 +447,9 @@ void ath_beacon_tasklet(unsigned long data) | |||
447 | vif = sc->beacon.bslot[slot]; | 447 | vif = sc->beacon.bslot[slot]; |
448 | aphy = sc->beacon.bslot_aphy[slot]; | 448 | aphy = sc->beacon.bslot_aphy[slot]; |
449 | 449 | ||
450 | DPRINTF(sc, ATH_DBG_BEACON, | 450 | ath_print(common, ATH_DBG_BEACON, |
451 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | 451 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", |
452 | slot, tsf, tsftu, intval, vif); | 452 | slot, tsf, tsftu, intval, vif); |
453 | 453 | ||
454 | bfaddr = 0; | 454 | bfaddr = 0; |
455 | if (vif) { | 455 | if (vif) { |
@@ -480,7 +480,8 @@ void ath_beacon_tasklet(unsigned long data) | |||
480 | sc->beacon.updateslot = COMMIT; /* commit next beacon */ | 480 | sc->beacon.updateslot = COMMIT; /* commit next beacon */ |
481 | sc->beacon.slotupdate = slot; | 481 | sc->beacon.slotupdate = slot; |
482 | } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { | 482 | } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { |
483 | ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); | 483 | ah->slottime = sc->beacon.slottime; |
484 | ath9k_hw_init_global_settings(ah); | ||
484 | sc->beacon.updateslot = OK; | 485 | sc->beacon.updateslot = OK; |
485 | } | 486 | } |
486 | if (bfaddr != 0) { | 487 | if (bfaddr != 0) { |
@@ -490,7 +491,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
490 | * are still pending on the queue. | 491 | * are still pending on the queue. |
491 | */ | 492 | */ |
492 | if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { | 493 | if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { |
493 | DPRINTF(sc, ATH_DBG_FATAL, | 494 | ath_print(common, ATH_DBG_FATAL, |
494 | "beacon queue %u did not stop?\n", sc->beacon.beaconq); | 495 | "beacon queue %u did not stop?\n", sc->beacon.beaconq); |
495 | } | 496 | } |
496 | 497 | ||
@@ -502,6 +503,19 @@ void ath_beacon_tasklet(unsigned long data) | |||
502 | } | 503 | } |
503 | } | 504 | } |
504 | 505 | ||
506 | static void ath9k_beacon_init(struct ath_softc *sc, | ||
507 | u32 next_beacon, | ||
508 | u32 beacon_period) | ||
509 | { | ||
510 | if (beacon_period & ATH9K_BEACON_RESET_TSF) | ||
511 | ath9k_ps_wakeup(sc); | ||
512 | |||
513 | ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); | ||
514 | |||
515 | if (beacon_period & ATH9K_BEACON_RESET_TSF) | ||
516 | ath9k_ps_restore(sc); | ||
517 | } | ||
518 | |||
505 | /* | 519 | /* |
506 | * For multi-bss ap support beacons are either staggered evenly over N slots or | 520 | * For multi-bss ap support beacons are either staggered evenly over N slots or |
507 | * burst together. For the former arrange for the SWBA to be delivered for each | 521 | * burst together. For the former arrange for the SWBA to be delivered for each |
@@ -512,16 +526,13 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
512 | { | 526 | { |
513 | u32 nexttbtt, intval; | 527 | u32 nexttbtt, intval; |
514 | 528 | ||
515 | /* Configure the timers only when the TSF has to be reset */ | ||
516 | |||
517 | if (!(sc->sc_flags & SC_OP_TSF_RESET)) | ||
518 | return; | ||
519 | |||
520 | /* NB: the beacon interval is kept internally in TU's */ | 529 | /* NB: the beacon interval is kept internally in TU's */ |
521 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | 530 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; |
522 | intval /= ATH_BCBUF; /* for staggered beacons */ | 531 | intval /= ATH_BCBUF; /* for staggered beacons */ |
523 | nexttbtt = intval; | 532 | nexttbtt = intval; |
524 | intval |= ATH9K_BEACON_RESET_TSF; | 533 | |
534 | if (sc->sc_flags & SC_OP_TSF_RESET) | ||
535 | intval |= ATH9K_BEACON_RESET_TSF; | ||
525 | 536 | ||
526 | /* | 537 | /* |
527 | * In AP mode we enable the beacon timers and SWBA interrupts to | 538 | * In AP mode we enable the beacon timers and SWBA interrupts to |
@@ -534,7 +545,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
534 | /* Set the computed AP beacon timers */ | 545 | /* Set the computed AP beacon timers */ |
535 | 546 | ||
536 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 547 | ath9k_hw_set_interrupts(sc->sc_ah, 0); |
537 | ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); | 548 | ath9k_beacon_init(sc, nexttbtt, intval); |
538 | sc->beacon.bmisscnt = 0; | 549 | sc->beacon.bmisscnt = 0; |
539 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 550 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
540 | 551 | ||
@@ -555,6 +566,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
555 | static void ath_beacon_config_sta(struct ath_softc *sc, | 566 | static void ath_beacon_config_sta(struct ath_softc *sc, |
556 | struct ath_beacon_config *conf) | 567 | struct ath_beacon_config *conf) |
557 | { | 568 | { |
569 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
558 | struct ath9k_beacon_state bs; | 570 | struct ath9k_beacon_state bs; |
559 | int dtimperiod, dtimcount, sleepduration; | 571 | int dtimperiod, dtimcount, sleepduration; |
560 | int cfpperiod, cfpcount; | 572 | int cfpperiod, cfpcount; |
@@ -562,6 +574,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
562 | u64 tsf; | 574 | u64 tsf; |
563 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; | 575 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; |
564 | 576 | ||
577 | /* No need to configure beacon if we are not associated */ | ||
578 | if (!common->curaid) { | ||
579 | ath_print(common, ATH_DBG_BEACON, | ||
580 | "STA is not yet associated..skipping beacon config\n"); | ||
581 | return; | ||
582 | } | ||
583 | |||
565 | memset(&bs, 0, sizeof(bs)); | 584 | memset(&bs, 0, sizeof(bs)); |
566 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | 585 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; |
567 | 586 | ||
@@ -651,11 +670,11 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
651 | /* TSF out of range threshold fixed at 1 second */ | 670 | /* TSF out of range threshold fixed at 1 second */ |
652 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 671 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
653 | 672 | ||
654 | DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 673 | ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); |
655 | DPRINTF(sc, ATH_DBG_BEACON, | 674 | ath_print(common, ATH_DBG_BEACON, |
656 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 675 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
657 | bs.bs_bmissthreshold, bs.bs_sleepduration, | 676 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
658 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | 677 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); |
659 | 678 | ||
660 | /* Set the computed STA beacon timers */ | 679 | /* Set the computed STA beacon timers */ |
661 | 680 | ||
@@ -669,6 +688,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
669 | struct ath_beacon_config *conf, | 688 | struct ath_beacon_config *conf, |
670 | struct ieee80211_vif *vif) | 689 | struct ieee80211_vif *vif) |
671 | { | 690 | { |
691 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
672 | u64 tsf; | 692 | u64 tsf; |
673 | u32 tsftu, intval, nexttbtt; | 693 | u32 tsftu, intval, nexttbtt; |
674 | 694 | ||
@@ -689,9 +709,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
689 | nexttbtt += intval; | 709 | nexttbtt += intval; |
690 | } while (nexttbtt < tsftu); | 710 | } while (nexttbtt < tsftu); |
691 | 711 | ||
692 | DPRINTF(sc, ATH_DBG_BEACON, | 712 | ath_print(common, ATH_DBG_BEACON, |
693 | "IBSS nexttbtt %u intval %u (%u)\n", | 713 | "IBSS nexttbtt %u intval %u (%u)\n", |
694 | nexttbtt, intval, conf->beacon_interval); | 714 | nexttbtt, intval, conf->beacon_interval); |
695 | 715 | ||
696 | /* | 716 | /* |
697 | * In IBSS mode enable the beacon timers but only enable SWBA interrupts | 717 | * In IBSS mode enable the beacon timers but only enable SWBA interrupts |
@@ -707,7 +727,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
707 | /* Set the computed ADHOC beacon timers */ | 727 | /* Set the computed ADHOC beacon timers */ |
708 | 728 | ||
709 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 729 | ath9k_hw_set_interrupts(sc->sc_ah, 0); |
710 | ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); | 730 | ath9k_beacon_init(sc, nexttbtt, intval); |
711 | sc->beacon.bmisscnt = 0; | 731 | sc->beacon.bmisscnt = 0; |
712 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 732 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
713 | 733 | ||
@@ -719,10 +739,10 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
719 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | 739 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) |
720 | { | 740 | { |
721 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | 741 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; |
742 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
722 | enum nl80211_iftype iftype; | 743 | enum nl80211_iftype iftype; |
723 | 744 | ||
724 | /* Setup the beacon configuration parameters */ | 745 | /* Setup the beacon configuration parameters */ |
725 | |||
726 | if (vif) { | 746 | if (vif) { |
727 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 747 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
728 | 748 | ||
@@ -759,8 +779,8 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
759 | ath_beacon_config_sta(sc, cur_conf); | 779 | ath_beacon_config_sta(sc, cur_conf); |
760 | break; | 780 | break; |
761 | default: | 781 | default: |
762 | DPRINTF(sc, ATH_DBG_CONFIG, | 782 | ath_print(common, ATH_DBG_CONFIG, |
763 | "Unsupported beaconing mode\n"); | 783 | "Unsupported beaconing mode\n"); |
764 | return; | 784 | return; |
765 | } | 785 | } |
766 | 786 | ||