ath9k: remove the bf->aphy field
[deliverable/linux.git] / drivers / net / wireless / ath / ath9k / beacon.c
CommitLineData
f078f209 1/*
cee075a2 2 * Copyright (c) 2008-2009 Atheros Communications Inc.
f078f209
LR
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
394cf0a1 17#include "ath9k.h"
f078f209 18
5379c8a2
S
19#define FUDGE 2
20
f078f209 21/*
f078f209
LR
22 * This function will modify certain transmit queue properties depending on
23 * the operating mode of the station (AP or AdHoc). Parameters are AIFS
24 * settings and channel width min/max
25*/
94db2936 26int ath_beaconq_config(struct ath_softc *sc)
f078f209 27{
cbe61d8a 28 struct ath_hw *ah = sc->sc_ah;
c46917bb 29 struct ath_common *common = ath9k_hw_common(ah);
94db2936 30 struct ath9k_tx_queue_info qi, qi_be;
066dae93 31 struct ath_txq *txq;
f078f209 32
b77f483f 33 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
2660b81a 34 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
f078f209
LR
35 /* Always burst out beacon and CAB traffic. */
36 qi.tqi_aifs = 1;
37 qi.tqi_cwmin = 0;
38 qi.tqi_cwmax = 0;
39 } else {
40 /* Adhoc mode; important thing is to use 2x cwmin. */
066dae93
FF
41 txq = sc->tx.txq_map[WME_AC_BE];
42 ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
94db2936
VN
43 qi.tqi_aifs = qi_be.tqi_aifs;
44 qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
45 qi.tqi_cwmax = qi_be.tqi_cwmax;
f078f209
LR
46 }
47
b77f483f 48 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
3800276a
JP
49 ath_err(common,
50 "Unable to update h/w beacon queue parameters\n");
f078f209
LR
51 return 0;
52 } else {
9fc9ab0a 53 ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
f078f209
LR
54 return 1;
55 }
56}
57
58/*
f078f209
LR
59 * Associates the beacon frame buffer with a transmit descriptor. Will set
60 * up all required antenna switch parameters, rate codes, and channel flags.
61 * Beacons are always sent out at the lowest rate, and are not retried.
62*/
9fc9ab0a 63static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
64b84010 64 struct ath_buf *bf, int rateidx)
f078f209 65{
a22be22a 66 struct sk_buff *skb = bf->bf_mpdu;
cbe61d8a 67 struct ath_hw *ah = sc->sc_ah;
43c27613 68 struct ath_common *common = ath9k_hw_common(ah);
f078f209 69 struct ath_desc *ds;
980b24da 70 struct ath9k_11n_rate_series series[4];
9fc9ab0a 71 int flags, antenna, ctsrate = 0, ctsduration = 0;
545750d3
FF
72 struct ieee80211_supported_band *sband;
73 u8 rate = 0;
f078f209 74
f078f209 75 ds = bf->bf_desc;
f078f209
LR
76 flags = ATH9K_TXDESC_NOACK;
77
a65e4cb4
FF
78 ds->ds_link = 0;
79 /*
80 * Switch antenna every beacon.
81 * Should only switch every beacon period, not for every SWBA
82 * XXX assumes two antennae
83 */
84 antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
f078f209 85
545750d3 86 sband = &sc->sbands[common->hw->conf.channel->band];
64b84010 87 rate = sband->bitrates[rateidx].hw_value;
672840ac 88 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
64b84010 89 rate |= sband->bitrates[rateidx].hw_value_short;
9fc9ab0a
S
90
91 ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
92 ATH9K_PKT_TYPE_BEACON,
93 MAX_RATE_POWER,
94 ATH9K_TXKEYIX_INVALID,
95 ATH9K_KEY_TYPE_CLEAR,
96 flags);
f078f209
LR
97
98 /* NB: beacon's BufLen must be a multiple of 4 bytes */
9fc9ab0a 99 ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
cc610ac0
VT
100 true, true, ds, bf->bf_buf_addr,
101 sc->beacon.beaconq);
f078f209 102
0345f37b 103 memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
f078f209
LR
104 series[0].Tries = 1;
105 series[0].Rate = rate;
ea066d5a
MSS
106 series[0].ChSel = ath_txchainmask_reduction(sc,
107 common->tx_chainmask, series[0].Rate);
f078f209 108 series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
9fc9ab0a
S
109 ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
110 series, 4, 0);
f078f209
LR
111}
112
28d16708
FF
113static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
114{
115 struct ath_wiphy *aphy = hw->priv;
116 struct ath_softc *sc = aphy->sc;
117 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
118 struct ath_tx_control txctl;
119
120 memset(&txctl, 0, sizeof(struct ath_tx_control));
121 txctl.txq = sc->beacon.cabq;
122
226afe68
JP
123 ath_dbg(common, ATH_DBG_XMIT,
124 "transmitting CABQ packet, skb: %p\n", skb);
28d16708
FF
125
126 if (ath_tx_start(hw, skb, &txctl) != 0) {
226afe68 127 ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n");
28d16708
FF
128 dev_kfree_skb_any(skb);
129 }
130}
131
c52f33d0 132static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
2c3db3d5 133 struct ieee80211_vif *vif)
f078f209 134{
c52f33d0
JM
135 struct ath_wiphy *aphy = hw->priv;
136 struct ath_softc *sc = aphy->sc;
c46917bb 137 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
f078f209 138 struct ath_buf *bf;
17d7904d 139 struct ath_vif *avp;
f078f209 140 struct sk_buff *skb;
f078f209 141 struct ath_txq *cabq;
147583c0 142 struct ieee80211_tx_info *info;
980b24da
S
143 int cabq_depth;
144
5640b08e 145 avp = (void *)vif->drv_priv;
b77f483f 146 cabq = sc->beacon.cabq;
f078f209 147
d8baa939 148 if (avp->av_bcbuf == NULL)
f078f209 149 return NULL;
980b24da 150
9fc9ab0a
S
151 /* Release the old beacon first */
152
f078f209 153 bf = avp->av_bcbuf;
a22be22a 154 skb = bf->bf_mpdu;
a8fff50e 155 if (skb) {
c1739eb3 156 dma_unmap_single(sc->dev, bf->bf_buf_addr,
9fc9ab0a 157 skb->len, DMA_TO_DEVICE);
3fbb9d95 158 dev_kfree_skb_any(skb);
6cf9e995 159 bf->bf_buf_addr = 0;
a8fff50e 160 }
f078f209 161
9fc9ab0a
S
162 /* Get a new beacon from mac80211 */
163
c52f33d0 164 skb = ieee80211_beacon_get(hw, vif);
a8fff50e
JM
165 bf->bf_mpdu = skb;
166 if (skb == NULL)
167 return NULL;
4ed96f04
JM
168 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
169 avp->tsf_adjust;
980b24da 170
147583c0
JM
171 info = IEEE80211_SKB_CB(skb);
172 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
173 /*
174 * TODO: make sure the seq# gets assigned properly (vs. other
175 * TX frames)
176 */
980b24da 177 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
b77f483f 178 sc->tx.seq_no += 0x10;
147583c0 179 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
b77f483f 180 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
147583c0 181 }
980b24da 182
c1739eb3
BG
183 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
184 skb->len, DMA_TO_DEVICE);
7da3c55c 185 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
f8316df1
LR
186 dev_kfree_skb_any(skb);
187 bf->bf_mpdu = NULL;
6cf9e995 188 bf->bf_buf_addr = 0;
3800276a 189 ath_err(common, "dma_mapping_error on beaconing\n");
f8316df1
LR
190 return NULL;
191 }
f078f209 192
c52f33d0 193 skb = ieee80211_get_buffered_bc(hw, vif);
f078f209 194
f078f209
LR
195 /*
196 * if the CABQ traffic from previous DTIM is pending and the current
197 * beacon is also a DTIM.
17d7904d
S
198 * 1) if there is only one vif let the cab traffic continue.
199 * 2) if there are more than one vif and we are using staggered
f078f209 200 * beacons, then drain the cabq by dropping all the frames in
17d7904d 201 * the cabq so that the current vifs cab traffic can be scheduled.
f078f209
LR
202 */
203 spin_lock_bh(&cabq->axq_lock);
204 cabq_depth = cabq->axq_depth;
205 spin_unlock_bh(&cabq->axq_lock);
206
e022edbd 207 if (skb && cabq_depth) {
17d7904d 208 if (sc->nvifs > 1) {
226afe68
JP
209 ath_dbg(common, ATH_DBG_BEACON,
210 "Flushing previous cabq traffic\n");
9fc9ab0a 211 ath_draintxq(sc, cabq, false);
f078f209
LR
212 }
213 }
214
64b84010 215 ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx);
f078f209 216
e022edbd 217 while (skb) {
c52f33d0
JM
218 ath_tx_cabq(hw, skb);
219 skb = ieee80211_get_buffered_bc(hw, vif);
e022edbd 220 }
f078f209 221
f078f209
LR
222 return bf;
223}
224
c52f33d0 225int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
f078f209 226{
c52f33d0 227 struct ath_softc *sc = aphy->sc;
c46917bb 228 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
17d7904d 229 struct ath_vif *avp;
f078f209
LR
230 struct ath_buf *bf;
231 struct sk_buff *skb;
459f5f90 232 __le64 tstamp;
f078f209 233
5640b08e 234 avp = (void *)vif->drv_priv;
f078f209
LR
235
236 /* Allocate a beacon descriptor if we haven't done so. */
237 if (!avp->av_bcbuf) {
980b24da
S
238 /* Allocate beacon state for hostap/ibss. We know
239 * a buffer is available. */
b77f483f 240 avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
980b24da 241 struct ath_buf, list);
f078f209
LR
242 list_del(&avp->av_bcbuf->list);
243
4801416c 244 if (ath9k_uses_beacons(vif->type)) {
f078f209
LR
245 int slot;
246 /*
17d7904d 247 * Assign the vif to a beacon xmit slot. As
f078f209
LR
248 * above, this cannot fail to find one.
249 */
250 avp->av_bslot = 0;
251 for (slot = 0; slot < ATH_BCBUF; slot++)
2c3db3d5 252 if (sc->beacon.bslot[slot] == NULL) {
f078f209 253 avp->av_bslot = slot;
774610e4 254
f078f209 255 /* NB: keep looking for a double slot */
774610e4
FF
256 if (slot == 0 || !sc->beacon.bslot[slot-1])
257 break;
f078f209 258 }
2c3db3d5
JM
259 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
260 sc->beacon.bslot[avp->av_bslot] = vif;
17d7904d 261 sc->nbcnvifs++;
f078f209
LR
262 }
263 }
264
9fc9ab0a 265 /* release the previous beacon frame, if it already exists. */
f078f209
LR
266 bf = avp->av_bcbuf;
267 if (bf->bf_mpdu != NULL) {
a22be22a 268 skb = bf->bf_mpdu;
c1739eb3 269 dma_unmap_single(sc->dev, bf->bf_buf_addr,
9fc9ab0a 270 skb->len, DMA_TO_DEVICE);
f078f209
LR
271 dev_kfree_skb_any(skb);
272 bf->bf_mpdu = NULL;
6cf9e995 273 bf->bf_buf_addr = 0;
f078f209
LR
274 }
275
9fc9ab0a 276 /* NB: the beacon data buffer must be 32-bit aligned. */
5640b08e 277 skb = ieee80211_beacon_get(sc->hw, vif);
d7e86c32 278 if (skb == NULL)
f078f209 279 return -ENOMEM;
f078f209 280
459f5f90 281 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
b77f483f 282 sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
4ed96f04 283 /* Calculate a TSF adjustment factor required for staggered beacons. */
f078f209
LR
284 if (avp->av_bslot > 0) {
285 u64 tsfadjust;
f078f209
LR
286 int intval;
287
57c4d7b4 288 intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
f078f209
LR
289
290 /*
4ed96f04
JM
291 * Calculate the TSF offset for this beacon slot, i.e., the
292 * number of usecs that need to be added to the timestamp field
293 * in Beacon and Probe Response frames. Beacon slot 0 is
294 * processed at the correct offset, so it does not require TSF
295 * adjustment. Other slots are adjusted to get the timestamp
296 * close to the TBTT for the BSS.
f078f209 297 */
4ed96f04
JM
298 tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
299 avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
f078f209 300
226afe68
JP
301 ath_dbg(common, ATH_DBG_BEACON,
302 "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
303 avp->av_bslot, intval, (unsigned long long)tsfadjust);
f078f209 304
4ed96f04
JM
305 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
306 avp->tsf_adjust;
307 } else
308 avp->tsf_adjust = cpu_to_le64(0);
f078f209 309
f8316df1 310 bf->bf_mpdu = skb;
c1739eb3
BG
311 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
312 skb->len, DMA_TO_DEVICE);
7da3c55c 313 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
f8316df1
LR
314 dev_kfree_skb_any(skb);
315 bf->bf_mpdu = NULL;
6cf9e995 316 bf->bf_buf_addr = 0;
3800276a 317 ath_err(common, "dma_mapping_error on beacon alloc\n");
f8316df1
LR
318 return -ENOMEM;
319 }
f078f209
LR
320
321 return 0;
322}
323
17d7904d 324void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
f078f209
LR
325{
326 if (avp->av_bcbuf != NULL) {
327 struct ath_buf *bf;
328
329 if (avp->av_bslot != -1) {
2c3db3d5 330 sc->beacon.bslot[avp->av_bslot] = NULL;
17d7904d 331 sc->nbcnvifs--;
f078f209
LR
332 }
333
334 bf = avp->av_bcbuf;
335 if (bf->bf_mpdu != NULL) {
a22be22a 336 struct sk_buff *skb = bf->bf_mpdu;
c1739eb3 337 dma_unmap_single(sc->dev, bf->bf_buf_addr,
9fc9ab0a 338 skb->len, DMA_TO_DEVICE);
f078f209
LR
339 dev_kfree_skb_any(skb);
340 bf->bf_mpdu = NULL;
6cf9e995 341 bf->bf_buf_addr = 0;
f078f209 342 }
b77f483f 343 list_add_tail(&bf->list, &sc->beacon.bbuf);
f078f209
LR
344
345 avp->av_bcbuf = NULL;
346 }
347}
348
9fc9ab0a 349void ath_beacon_tasklet(unsigned long data)
f078f209 350{
f078f209 351 struct ath_softc *sc = (struct ath_softc *)data;
cbe61d8a 352 struct ath_hw *ah = sc->sc_ah;
c46917bb 353 struct ath_common *common = ath9k_hw_common(ah);
f078f209 354 struct ath_buf *bf = NULL;
2c3db3d5
JM
355 struct ieee80211_vif *vif;
356 int slot;
9546aae0 357 u32 bfaddr, bc = 0, tsftu;
f078f209 358 u64 tsf;
f078f209
LR
359 u16 intval;
360
f078f209
LR
361 /*
362 * Check if the previous beacon has gone out. If
363 * not don't try to post another, skip this period
364 * and wait for the next. Missed beacons indicate
365 * a problem and should not occur. If we miss too
366 * many consecutive beacons reset the device.
367 */
b77f483f
S
368 if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
369 sc->beacon.bmisscnt++;
9546aae0 370
b77f483f 371 if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
226afe68
JP
372 ath_dbg(common, ATH_DBG_BSTUCK,
373 "missed %u consecutive beacons\n",
374 sc->beacon.bmisscnt);
70cf1533 375 ath9k_hw_bstuck_nfcal(ah);
b77f483f 376 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
226afe68
JP
377 ath_dbg(common, ATH_DBG_BSTUCK,
378 "beacon is officially stuck\n");
b74444f8 379 sc->sc_flags |= SC_OP_TSF_RESET;
fac6b6a0 380 ath_reset(sc, true);
f078f209 381 }
9546aae0 382
f078f209
LR
383 return;
384 }
980b24da 385
b77f483f 386 if (sc->beacon.bmisscnt != 0) {
226afe68
JP
387 ath_dbg(common, ATH_DBG_BSTUCK,
388 "resume beacon xmit after %u misses\n",
389 sc->beacon.bmisscnt);
b77f483f 390 sc->beacon.bmisscnt = 0;
f078f209
LR
391 }
392
393 /*
394 * Generate beacon frames. we are sending frames
395 * staggered so calculate the slot for this frame based
396 * on the tsf to safeguard against missing an swba.
397 */
398
57c4d7b4 399 intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
f078f209
LR
400
401 tsf = ath9k_hw_gettsf64(ah);
402 tsftu = TSF_TO_TU(tsf>>32, tsf);
403 slot = ((tsftu % intval) * ATH_BCBUF) / intval;
4ed96f04
JM
404 /*
405 * Reverse the slot order to get slot 0 on the TBTT offset that does
406 * not require TSF adjustment and other slots adding
407 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
408 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
409 * and slot 0 is at correct offset to TBTT.
410 */
411 slot = ATH_BCBUF - slot - 1;
412 vif = sc->beacon.bslot[slot];
980b24da 413
226afe68
JP
414 ath_dbg(common, ATH_DBG_BEACON,
415 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
416 slot, tsf, tsftu, intval, vif);
980b24da 417
f078f209 418 bfaddr = 0;
2c3db3d5 419 if (vif) {
7545daf4 420 bf = ath_beacon_generate(sc->hw, vif);
f078f209
LR
421 if (bf != NULL) {
422 bfaddr = bf->bf_daddr;
423 bc = 1;
424 }
425 }
9546aae0 426
f078f209
LR
427 /*
428 * Handle slot time change when a non-ERP station joins/leaves
429 * an 11g network. The 802.11 layer notifies us via callback,
430 * we mark updateslot, then wait one beacon before effecting
431 * the change. This gives associated stations at least one
432 * beacon interval to note the state change.
433 *
434 * NB: The slot time change state machine is clocked according
435 * to whether we are bursting or staggering beacons. We
436 * recognize the request to update and record the current
437 * slot then don't transition until that slot is reached
438 * again. If we miss a beacon for that slot then we'll be
439 * slow to transition but we'll be sure at least one beacon
440 * interval has passed. When bursting slot is always left
441 * set to ATH_BCBUF so this check is a noop.
442 */
b77f483f
S
443 if (sc->beacon.updateslot == UPDATE) {
444 sc->beacon.updateslot = COMMIT; /* commit next beacon */
445 sc->beacon.slotupdate = slot;
446 } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
0005baf4
FF
447 ah->slottime = sc->beacon.slottime;
448 ath9k_hw_init_global_settings(ah);
b77f483f 449 sc->beacon.updateslot = OK;
ff37e337 450 }
f078f209
LR
451 if (bfaddr != 0) {
452 /*
453 * Stop any current dma and put the new frame(s) on the queue.
454 * This should never fail since we check above that no frames
455 * are still pending on the queue.
456 */
b77f483f 457 if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
3800276a
JP
458 ath_err(common, "beacon queue %u did not stop?\n",
459 sc->beacon.beaconq);
f078f209
LR
460 }
461
462 /* NB: cabq traffic should already be queued and primed */
b77f483f
S
463 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
464 ath9k_hw_txstart(ah, sc->beacon.beaconq);
f078f209 465
17d7904d 466 sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
f078f209 467 }
f078f209
LR
468}
469
21526d57
LR
470static void ath9k_beacon_init(struct ath_softc *sc,
471 u32 next_beacon,
472 u32 beacon_period)
473{
474 if (beacon_period & ATH9K_BEACON_RESET_TSF)
475 ath9k_ps_wakeup(sc);
476
477 ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period);
478
479 if (beacon_period & ATH9K_BEACON_RESET_TSF)
480 ath9k_ps_restore(sc);
481}
482
f078f209 483/*
5379c8a2
S
484 * For multi-bss ap support beacons are either staggered evenly over N slots or
485 * burst together. For the former arrange for the SWBA to be delivered for each
486 * slot. Slots that are not occupied will generate nothing.
f078f209 487 */
5379c8a2 488static void ath_beacon_config_ap(struct ath_softc *sc,
d31e20af 489 struct ath_beacon_config *conf)
f078f209 490{
3069168c 491 struct ath_hw *ah = sc->sc_ah;
980b24da 492 u32 nexttbtt, intval;
f078f209 493
5379c8a2
S
494 /* NB: the beacon interval is kept internally in TU's */
495 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
496 intval /= ATH_BCBUF; /* for staggered beacons */
497 nexttbtt = intval;
d8728ee9
FF
498
499 if (sc->sc_flags & SC_OP_TSF_RESET)
500 intval |= ATH9K_BEACON_RESET_TSF;
f078f209 501
5379c8a2
S
502 /*
503 * In AP mode we enable the beacon timers and SWBA interrupts to
504 * prepare beacon frames.
505 */
506 intval |= ATH9K_BEACON_ENA;
3069168c 507 ah->imask |= ATH9K_INT_SWBA;
5379c8a2 508 ath_beaconq_config(sc);
f078f209 509
5379c8a2 510 /* Set the computed AP beacon timers */
f078f209 511
4df3071e 512 ath9k_hw_disable_interrupts(ah);
21526d57 513 ath9k_beacon_init(sc, nexttbtt, intval);
5379c8a2 514 sc->beacon.bmisscnt = 0;
3069168c 515 ath9k_hw_set_interrupts(ah, ah->imask);
b238e90e
S
516
517 /* Clear the reset TSF flag, so that subsequent beacon updation
518 will not reset the HW TSF. */
519
520 sc->sc_flags &= ~SC_OP_TSF_RESET;
5379c8a2 521}
459f5f90 522
5379c8a2
S
523/*
524 * This sets up the beacon timers according to the timestamp of the last
525 * received beacon and the current TSF, configures PCF and DTIM
526 * handling, programs the sleep registers so the hardware will wakeup in
527 * time to receive beacons, and configures the beacon miss handling so
528 * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
529 * we've associated with.
530 */
531static void ath_beacon_config_sta(struct ath_softc *sc,
d31e20af 532 struct ath_beacon_config *conf)
5379c8a2 533{
3069168c
PR
534 struct ath_hw *ah = sc->sc_ah;
535 struct ath_common *common = ath9k_hw_common(ah);
5379c8a2
S
536 struct ath9k_beacon_state bs;
537 int dtimperiod, dtimcount, sleepduration;
538 int cfpperiod, cfpcount;
539 u32 nexttbtt = 0, intval, tsftu;
540 u64 tsf;
267a9012 541 int num_beacons, offset, dtim_dec_count, cfp_dec_count;
5379c8a2 542
1a20034a
SB
543 /* No need to configure beacon if we are not associated */
544 if (!common->curaid) {
226afe68
JP
545 ath_dbg(common, ATH_DBG_BEACON,
546 "STA is not yet associated..skipping beacon config\n");
1a20034a
SB
547 return;
548 }
549
5379c8a2
S
550 memset(&bs, 0, sizeof(bs));
551 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
552
553 /*
554 * Setup dtim and cfp parameters according to
555 * last beacon we received (which may be none).
556 */
557 dtimperiod = conf->dtim_period;
5379c8a2
S
558 dtimcount = conf->dtim_count;
559 if (dtimcount >= dtimperiod) /* NB: sanity check */
560 dtimcount = 0;
561 cfpperiod = 1; /* NB: no PCF support yet */
562 cfpcount = 0;
563
564 sleepduration = conf->listen_interval * intval;
5379c8a2
S
565
566 /*
567 * Pull nexttbtt forward to reflect the current
568 * TSF and calculate dtim+cfp state for the result.
569 */
3069168c 570 tsf = ath9k_hw_gettsf64(ah);
5379c8a2 571 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
267a9012
JM
572
573 num_beacons = tsftu / intval + 1;
574 offset = tsftu % intval;
575 nexttbtt = tsftu - offset;
576 if (offset)
5379c8a2 577 nexttbtt += intval;
267a9012
JM
578
579 /* DTIM Beacon every dtimperiod Beacon */
580 dtim_dec_count = num_beacons % dtimperiod;
581 /* CFP every cfpperiod DTIM Beacon */
582 cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
583 if (dtim_dec_count)
584 cfp_dec_count++;
585
586 dtimcount -= dtim_dec_count;
587 if (dtimcount < 0)
588 dtimcount += dtimperiod;
589
590 cfpcount -= cfp_dec_count;
591 if (cfpcount < 0)
592 cfpcount += cfpperiod;
5379c8a2
S
593
594 bs.bs_intval = intval;
595 bs.bs_nexttbtt = nexttbtt;
596 bs.bs_dtimperiod = dtimperiod*intval;
597 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
598 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
599 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
600 bs.bs_cfpmaxduration = 0;
601
602 /*
603 * Calculate the number of consecutive beacons to miss* before taking
604 * a BMISS interrupt. The configuration is specified in TU so we only
605 * need calculate based on the beacon interval. Note that we clamp the
606 * result to at most 15 beacons.
607 */
608 if (sleepduration > intval) {
609 bs.bs_bmissthreshold = conf->listen_interval *
610 ATH_DEFAULT_BMISS_LIMIT / 2;
f078f209 611 } else {
5379c8a2
S
612 bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval);
613 if (bs.bs_bmissthreshold > 15)
614 bs.bs_bmissthreshold = 15;
615 else if (bs.bs_bmissthreshold <= 0)
616 bs.bs_bmissthreshold = 1;
f078f209
LR
617 }
618
5379c8a2
S
619 /*
620 * Calculate sleep duration. The configuration is given in ms.
621 * We ensure a multiple of the beacon period is used. Also, if the sleep
622 * duration is greater than the DTIM period then it makes senses
623 * to make it a multiple of that.
624 *
625 * XXX fixed at 100ms
626 */
980b24da 627
5379c8a2
S
628 bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
629 if (bs.bs_sleepduration > bs.bs_dtimperiod)
630 bs.bs_sleepduration = bs.bs_dtimperiod;
980b24da 631
5379c8a2
S
632 /* TSF out of range threshold fixed at 1 second */
633 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
f078f209 634
226afe68
JP
635 ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
636 ath_dbg(common, ATH_DBG_BEACON,
637 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
638 bs.bs_bmissthreshold, bs.bs_sleepduration,
639 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
f078f209 640
5379c8a2 641 /* Set the computed STA beacon timers */
980b24da 642
4df3071e 643 ath9k_hw_disable_interrupts(ah);
3069168c
PR
644 ath9k_hw_set_sta_beacon_timers(ah, &bs);
645 ah->imask |= ATH9K_INT_BMISS;
646 ath9k_hw_set_interrupts(ah, ah->imask);
5379c8a2 647}
f078f209 648
5379c8a2 649static void ath_beacon_config_adhoc(struct ath_softc *sc,
ee832d3e 650 struct ath_beacon_config *conf)
5379c8a2 651{
3069168c
PR
652 struct ath_hw *ah = sc->sc_ah;
653 struct ath_common *common = ath9k_hw_common(ah);
5379c8a2
S
654 u64 tsf;
655 u32 tsftu, intval, nexttbtt;
f078f209 656
5379c8a2 657 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
f078f209 658
546256fb 659
5379c8a2 660 /* Pull nexttbtt forward to reflect the current TSF */
4af9cf4f 661
5379c8a2
S
662 nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
663 if (nexttbtt == 0)
664 nexttbtt = intval;
665 else if (intval)
666 nexttbtt = roundup(nexttbtt, intval);
9fc9ab0a 667
3069168c 668 tsf = ath9k_hw_gettsf64(ah);
5379c8a2
S
669 tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
670 do {
671 nexttbtt += intval;
672 } while (nexttbtt < tsftu);
f078f209 673
226afe68
JP
674 ath_dbg(common, ATH_DBG_BEACON,
675 "IBSS nexttbtt %u intval %u (%u)\n",
676 nexttbtt, intval, conf->beacon_interval);
9fc9ab0a 677
5379c8a2
S
678 /*
679 * In IBSS mode enable the beacon timers but only enable SWBA interrupts
680 * if we need to manually prepare beacon frames. Otherwise we use a
681 * self-linked tx descriptor and let the hardware deal with things.
682 */
683 intval |= ATH9K_BEACON_ENA;
a65e4cb4 684 ah->imask |= ATH9K_INT_SWBA;
9fc9ab0a 685
5379c8a2
S
686 ath_beaconq_config(sc);
687
688 /* Set the computed ADHOC beacon timers */
689
4df3071e 690 ath9k_hw_disable_interrupts(ah);
21526d57 691 ath9k_beacon_init(sc, nexttbtt, intval);
5379c8a2 692 sc->beacon.bmisscnt = 0;
3069168c 693 ath9k_hw_set_interrupts(ah, ah->imask);
f078f209
LR
694}
695
2c3db3d5 696void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
f078f209 697{
6b96f93e 698 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
c46917bb 699 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
6b96f93e 700 enum nl80211_iftype iftype;
5379c8a2
S
701
702 /* Setup the beacon configuration parameters */
2c3db3d5 703 if (vif) {
6b96f93e 704 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
6b96f93e 705 iftype = vif->type;
6b96f93e
VT
706 cur_conf->beacon_interval = bss_conf->beacon_int;
707 cur_conf->dtim_period = bss_conf->dtim_period;
ee832d3e
MSS
708 } else {
709 iftype = sc->sc_ah->opmode;
710 }
711
4801416c
BG
712 cur_conf->listen_interval = 1;
713 cur_conf->dtim_count = 1;
714 cur_conf->bmiss_timeout =
715 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
6b96f93e 716
c4f9f16b
VT
717 /*
718 * It looks like mac80211 may end up using beacon interval of zero in
719 * some cases (at least for mesh point). Avoid getting into an
720 * infinite loop by using a bit safer value instead. To be safe,
721 * do sanity check on beacon interval for all operating modes.
722 */
723 if (cur_conf->beacon_interval == 0)
724 cur_conf->beacon_interval = 100;
6b96f93e 725
ee832d3e
MSS
726 /*
727 * Some times we dont parse dtim period from mac80211, in that case
728 * use a default value
729 */
730 if (cur_conf->dtim_period == 0)
731 cur_conf->dtim_period = 1;
732
6b96f93e
VT
733 switch (iftype) {
734 case NL80211_IFTYPE_AP:
735 ath_beacon_config_ap(sc, cur_conf);
736 break;
737 case NL80211_IFTYPE_ADHOC:
738 case NL80211_IFTYPE_MESH_POINT:
ee832d3e 739 ath_beacon_config_adhoc(sc, cur_conf);
6b96f93e
VT
740 break;
741 case NL80211_IFTYPE_STATION:
742 ath_beacon_config_sta(sc, cur_conf);
743 break;
744 default:
226afe68
JP
745 ath_dbg(common, ATH_DBG_CONFIG,
746 "Unsupported beaconing mode\n");
6b96f93e
VT
747 return;
748 }
749
750 sc->sc_flags |= SC_OP_BEACONS;
f078f209 751}
This page took 0.453807 seconds and 5 git commands to generate.