beacon.c revision ef4ad63368e6162fb0b18861748fac49edfcbd03
1/* 2 * Copyright (c) 2008-2011 Atheros Communications Inc. 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 17#include <linux/dma-mapping.h> 18#include "ath9k.h" 19 20#define FUDGE 2 21 22static void ath9k_reset_beacon_status(struct ath_softc *sc) 23{ 24 sc->beacon.tx_processed = false; 25 sc->beacon.tx_last = false; 26} 27 28/* 29 * This function will modify certain transmit queue properties depending on 30 * the operating mode of the station (AP or AdHoc). Parameters are AIFS 31 * settings and channel width min/max 32*/ 33int ath_beaconq_config(struct ath_softc *sc) 34{ 35 struct ath_hw *ah = sc->sc_ah; 36 struct ath_common *common = ath9k_hw_common(ah); 37 struct ath9k_tx_queue_info qi, qi_be; 38 struct ath_txq *txq; 39 40 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); 41 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 42 /* Always burst out beacon and CAB traffic. */ 43 qi.tqi_aifs = 1; 44 qi.tqi_cwmin = 0; 45 qi.tqi_cwmax = 0; 46 } else { 47 /* Adhoc mode; important thing is to use 2x cwmin. */ 48 txq = sc->tx.txq_map[WME_AC_BE]; 49 ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); 50 qi.tqi_aifs = qi_be.tqi_aifs; 51 if (ah->slottime == ATH9K_SLOT_TIME_20) 52 qi.tqi_cwmin = 2*qi_be.tqi_cwmin; 53 else 54 qi.tqi_cwmin = 4*qi_be.tqi_cwmin; 55 qi.tqi_cwmax = qi_be.tqi_cwmax; 56 } 57 58 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { 59 ath_err(common, 60 "Unable to update h/w beacon queue parameters\n"); 61 return 0; 62 } else { 63 ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); 64 return 1; 65 } 66} 67 68/* 69 * Associates the beacon frame buffer with a transmit descriptor. Will set 70 * up rate codes, and channel flags. Beacons are always sent out at the 71 * lowest rate, and are not retried. 72*/ 73static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, 74 struct ath_buf *bf, int rateidx) 75{ 76 struct sk_buff *skb = bf->bf_mpdu; 77 struct ath_hw *ah = sc->sc_ah; 78 struct ath_common *common = ath9k_hw_common(ah); 79 struct ath_tx_info info; 80 struct ieee80211_supported_band *sband; 81 u8 chainmask = ah->txchainmask; 82 u8 rate = 0; 83 84 ath9k_reset_beacon_status(sc); 85 86 sband = &sc->sbands[common->hw->conf.channel->band]; 87 rate = sband->bitrates[rateidx].hw_value; 88 if (vif->bss_conf.use_short_preamble) 89 rate |= sband->bitrates[rateidx].hw_value_short; 90 91 memset(&info, 0, sizeof(info)); 92 info.pkt_len = skb->len + FCS_LEN; 93 info.type = ATH9K_PKT_TYPE_BEACON; 94 info.txpower = MAX_RATE_POWER; 95 info.keyix = ATH9K_TXKEYIX_INVALID; 96 info.keytype = ATH9K_KEY_TYPE_CLEAR; 97 info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK; 98 99 info.buf_addr[0] = bf->bf_buf_addr; 100 info.buf_len[0] = roundup(skb->len, 4); 101 102 info.is_first = true; 103 info.is_last = true; 104 105 info.qcu = sc->beacon.beaconq; 106 107 info.rates[0].Tries = 1; 108 info.rates[0].Rate = rate; 109 info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate); 110 111 ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); 112} 113 114static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) 115{ 116 struct ath_softc *sc = hw->priv; 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 123 ath_dbg(common, XMIT, "transmitting CABQ packet, skb: %p\n", skb); 124 125 if (ath_tx_start(hw, skb, &txctl) != 0) { 126 ath_dbg(common, XMIT, "CABQ TX failed\n"); 127 dev_kfree_skb_any(skb); 128 } 129} 130 131static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, 132 struct ieee80211_vif *vif) 133{ 134 struct ath_softc *sc = hw->priv; 135 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 136 struct ath_buf *bf; 137 struct ath_vif *avp; 138 struct sk_buff *skb; 139 struct ath_txq *cabq; 140 struct ieee80211_tx_info *info; 141 int cabq_depth; 142 143 ath9k_reset_beacon_status(sc); 144 145 avp = (void *)vif->drv_priv; 146 cabq = sc->beacon.cabq; 147 148 if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active) 149 return NULL; 150 151 /* Release the old beacon first */ 152 153 bf = avp->av_bcbuf; 154 skb = bf->bf_mpdu; 155 if (skb) { 156 dma_unmap_single(sc->dev, bf->bf_buf_addr, 157 skb->len, DMA_TO_DEVICE); 158 dev_kfree_skb_any(skb); 159 bf->bf_buf_addr = 0; 160 } 161 162 /* Get a new beacon from mac80211 */ 163 164 skb = ieee80211_beacon_get(hw, vif); 165 bf->bf_mpdu = skb; 166 if (skb == NULL) 167 return NULL; 168 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = 169 avp->tsf_adjust; 170 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 */ 177 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 178 sc->tx.seq_no += 0x10; 179 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 180 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); 181 } 182 183 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, 184 skb->len, DMA_TO_DEVICE); 185 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { 186 dev_kfree_skb_any(skb); 187 bf->bf_mpdu = NULL; 188 bf->bf_buf_addr = 0; 189 ath_err(common, "dma_mapping_error on beaconing\n"); 190 return NULL; 191 } 192 193 skb = ieee80211_get_buffered_bc(hw, vif); 194 195 /* 196 * if the CABQ traffic from previous DTIM is pending and the current 197 * beacon is also a DTIM. 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 200 * beacons, then drain the cabq by dropping all the frames in 201 * the cabq so that the current vifs cab traffic can be scheduled. 202 */ 203 spin_lock_bh(&cabq->axq_lock); 204 cabq_depth = cabq->axq_depth; 205 spin_unlock_bh(&cabq->axq_lock); 206 207 if (skb && cabq_depth) { 208 if (sc->nvifs > 1) { 209 ath_dbg(common, BEACON, 210 "Flushing previous cabq traffic\n"); 211 ath_draintxq(sc, cabq, false); 212 } 213 } 214 215 ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx); 216 217 while (skb) { 218 ath_tx_cabq(hw, skb); 219 skb = ieee80211_get_buffered_bc(hw, vif); 220 } 221 222 return bf; 223} 224 225void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif) 226{ 227 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 228 struct ath_vif *avp = (void *)vif->drv_priv; 229 int slot; 230 231 avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list); 232 list_del(&avp->av_bcbuf->list); 233 234 for (slot = 0; slot < ATH_BCBUF; slot++) { 235 if (sc->beacon.bslot[slot] == NULL) { 236 avp->av_bslot = slot; 237 avp->is_bslot_active = false; 238 break; 239 } 240 } 241 242 sc->beacon.bslot[avp->av_bslot] = vif; 243 sc->nbcnvifs++; 244 245 ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", 246 avp->av_bslot); 247} 248 249void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif) 250{ 251 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 252 struct ath_vif *avp = (void *)vif->drv_priv; 253 struct ath_buf *bf = avp->av_bcbuf; 254 255 ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n", 256 avp->av_bslot); 257 258 tasklet_disable(&sc->bcon_tasklet); 259 260 if (bf && bf->bf_mpdu) { 261 struct sk_buff *skb = bf->bf_mpdu; 262 dma_unmap_single(sc->dev, bf->bf_buf_addr, 263 skb->len, DMA_TO_DEVICE); 264 dev_kfree_skb_any(skb); 265 bf->bf_mpdu = NULL; 266 bf->bf_buf_addr = 0; 267 } 268 269 avp->av_bcbuf = NULL; 270 avp->is_bslot_active = false; 271 sc->beacon.bslot[avp->av_bslot] = NULL; 272 sc->nbcnvifs--; 273 list_add_tail(&bf->list, &sc->beacon.bbuf); 274 275 tasklet_enable(&sc->bcon_tasklet); 276} 277 278void ath_beacon_tasklet(unsigned long data) 279{ 280 struct ath_softc *sc = (struct ath_softc *)data; 281 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 282 struct ath_hw *ah = sc->sc_ah; 283 struct ath_common *common = ath9k_hw_common(ah); 284 struct ath_buf *bf = NULL; 285 struct ieee80211_vif *vif; 286 bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); 287 int slot; 288 u32 bfaddr, bc = 0; 289 290 if (work_pending(&sc->hw_reset_work)) { 291 ath_dbg(common, RESET, 292 "reset work is pending, skip beaconing now\n"); 293 return; 294 } 295 /* 296 * Check if the previous beacon has gone out. If 297 * not don't try to post another, skip this period 298 * and wait for the next. Missed beacons indicate 299 * a problem and should not occur. If we miss too 300 * many consecutive beacons reset the device. 301 */ 302 if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { 303 sc->beacon.bmisscnt++; 304 305 if (!ath9k_hw_check_alive(ah)) 306 ieee80211_queue_work(sc->hw, &sc->hw_check_work); 307 308 if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { 309 ath_dbg(common, BSTUCK, 310 "missed %u consecutive beacons\n", 311 sc->beacon.bmisscnt); 312 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); 313 if (sc->beacon.bmisscnt > 3) 314 ath9k_hw_bstuck_nfcal(ah); 315 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { 316 ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); 317 sc->beacon.bmisscnt = 0; 318 ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 319 } 320 321 return; 322 } 323 324 /* 325 * Generate beacon frames. we are sending frames 326 * staggered so calculate the slot for this frame based 327 * on the tsf to safeguard against missing an swba. 328 */ 329 330 331 if (ah->opmode == NL80211_IFTYPE_AP) { 332 u16 intval; 333 u32 tsftu; 334 u64 tsf; 335 336 intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; 337 tsf = ath9k_hw_gettsf64(ah); 338 tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); 339 tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); 340 slot = (tsftu % (intval * ATH_BCBUF)) / intval; 341 vif = sc->beacon.bslot[slot]; 342 343 ath_dbg(common, BEACON, 344 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", 345 slot, tsf, tsftu / ATH_BCBUF, intval, vif); 346 } else { 347 slot = 0; 348 vif = sc->beacon.bslot[slot]; 349 } 350 351 352 bfaddr = 0; 353 if (vif) { 354 bf = ath_beacon_generate(sc->hw, vif); 355 if (bf != NULL) { 356 bfaddr = bf->bf_daddr; 357 bc = 1; 358 } 359 360 if (sc->beacon.bmisscnt != 0) { 361 ath_dbg(common, BSTUCK, 362 "resume beacon xmit after %u misses\n", 363 sc->beacon.bmisscnt); 364 sc->beacon.bmisscnt = 0; 365 } 366 } 367 368 /* 369 * Handle slot time change when a non-ERP station joins/leaves 370 * an 11g network. The 802.11 layer notifies us via callback, 371 * we mark updateslot, then wait one beacon before effecting 372 * the change. This gives associated stations at least one 373 * beacon interval to note the state change. 374 * 375 * NB: The slot time change state machine is clocked according 376 * to whether we are bursting or staggering beacons. We 377 * recognize the request to update and record the current 378 * slot then don't transition until that slot is reached 379 * again. If we miss a beacon for that slot then we'll be 380 * slow to transition but we'll be sure at least one beacon 381 * interval has passed. When bursting slot is always left 382 * set to ATH_BCBUF so this check is a noop. 383 */ 384 if (sc->beacon.updateslot == UPDATE) { 385 sc->beacon.updateslot = COMMIT; /* commit next beacon */ 386 sc->beacon.slotupdate = slot; 387 } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { 388 ah->slottime = sc->beacon.slottime; 389 ath9k_hw_init_global_settings(ah); 390 sc->beacon.updateslot = OK; 391 } 392 if (bfaddr != 0) { 393 /* NB: cabq traffic should already be queued and primed */ 394 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); 395 396 if (!edma) 397 ath9k_hw_txstart(ah, sc->beacon.beaconq); 398 399 sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ 400 } 401} 402 403static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval) 404{ 405 struct ath_hw *ah = sc->sc_ah; 406 407 ath9k_hw_disable_interrupts(ah); 408 ath9k_hw_reset_tsf(ah); 409 ath9k_hw_beaconinit(ah, nexttbtt, intval); 410 sc->beacon.bmisscnt = 0; 411 ath9k_hw_set_interrupts(ah); 412 ath9k_hw_enable_interrupts(ah); 413} 414 415/* 416 * For multi-bss ap support beacons are either staggered evenly over N slots or 417 * burst together. For the former arrange for the SWBA to be delivered for each 418 * slot. Slots that are not occupied will generate nothing. 419 */ 420static void ath9k_beacon_config_ap(struct ath_softc *sc, 421 struct ath_beacon_config *conf) 422{ 423 struct ath_hw *ah = sc->sc_ah; 424 struct ath_common *common = ath9k_hw_common(ah); 425 u32 nexttbtt, intval; 426 427 /* NB: the beacon interval is kept internally in TU's */ 428 intval = TU_TO_USEC(conf->beacon_interval); 429 intval /= ATH_BCBUF; 430 nexttbtt = intval; 431 432 if (conf->enable_beacon) 433 ah->imask |= ATH9K_INT_SWBA; 434 else 435 ah->imask &= ~ATH9K_INT_SWBA; 436 437 ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n", 438 nexttbtt, intval, conf->beacon_interval); 439 440 ath_beaconq_config(sc); 441 ath9k_beacon_init(sc, nexttbtt, intval); 442} 443 444/* 445 * This sets up the beacon timers according to the timestamp of the last 446 * received beacon and the current TSF, configures PCF and DTIM 447 * handling, programs the sleep registers so the hardware will wakeup in 448 * time to receive beacons, and configures the beacon miss handling so 449 * we'll receive a BMISS interrupt when we stop seeing beacons from the AP 450 * we've associated with. 451 */ 452static void ath9k_beacon_config_sta(struct ath_softc *sc, 453 struct ath_beacon_config *conf) 454{ 455 struct ath_hw *ah = sc->sc_ah; 456 struct ath_common *common = ath9k_hw_common(ah); 457 struct ath9k_beacon_state bs; 458 int dtimperiod, dtimcount, sleepduration; 459 int cfpperiod, cfpcount; 460 u32 nexttbtt = 0, intval, tsftu; 461 u64 tsf; 462 int num_beacons, offset, dtim_dec_count, cfp_dec_count; 463 464 /* No need to configure beacon if we are not associated */ 465 if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { 466 ath_dbg(common, BEACON, 467 "STA is not yet associated..skipping beacon config\n"); 468 return; 469 } 470 471 memset(&bs, 0, sizeof(bs)); 472 intval = conf->beacon_interval; 473 474 /* 475 * Setup dtim and cfp parameters according to 476 * last beacon we received (which may be none). 477 */ 478 dtimperiod = conf->dtim_period; 479 dtimcount = conf->dtim_count; 480 if (dtimcount >= dtimperiod) /* NB: sanity check */ 481 dtimcount = 0; 482 cfpperiod = 1; /* NB: no PCF support yet */ 483 cfpcount = 0; 484 485 sleepduration = conf->listen_interval * intval; 486 487 /* 488 * Pull nexttbtt forward to reflect the current 489 * TSF and calculate dtim+cfp state for the result. 490 */ 491 tsf = ath9k_hw_gettsf64(ah); 492 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 493 494 num_beacons = tsftu / intval + 1; 495 offset = tsftu % intval; 496 nexttbtt = tsftu - offset; 497 if (offset) 498 nexttbtt += intval; 499 500 /* DTIM Beacon every dtimperiod Beacon */ 501 dtim_dec_count = num_beacons % dtimperiod; 502 /* CFP every cfpperiod DTIM Beacon */ 503 cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; 504 if (dtim_dec_count) 505 cfp_dec_count++; 506 507 dtimcount -= dtim_dec_count; 508 if (dtimcount < 0) 509 dtimcount += dtimperiod; 510 511 cfpcount -= cfp_dec_count; 512 if (cfpcount < 0) 513 cfpcount += cfpperiod; 514 515 bs.bs_intval = intval; 516 bs.bs_nexttbtt = nexttbtt; 517 bs.bs_dtimperiod = dtimperiod*intval; 518 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; 519 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; 520 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; 521 bs.bs_cfpmaxduration = 0; 522 523 /* 524 * Calculate the number of consecutive beacons to miss* before taking 525 * a BMISS interrupt. The configuration is specified in TU so we only 526 * need calculate based on the beacon interval. Note that we clamp the 527 * result to at most 15 beacons. 528 */ 529 if (sleepduration > intval) { 530 bs.bs_bmissthreshold = conf->listen_interval * 531 ATH_DEFAULT_BMISS_LIMIT / 2; 532 } else { 533 bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval); 534 if (bs.bs_bmissthreshold > 15) 535 bs.bs_bmissthreshold = 15; 536 else if (bs.bs_bmissthreshold <= 0) 537 bs.bs_bmissthreshold = 1; 538 } 539 540 /* 541 * Calculate sleep duration. The configuration is given in ms. 542 * We ensure a multiple of the beacon period is used. Also, if the sleep 543 * duration is greater than the DTIM period then it makes senses 544 * to make it a multiple of that. 545 * 546 * XXX fixed at 100ms 547 */ 548 549 bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); 550 if (bs.bs_sleepduration > bs.bs_dtimperiod) 551 bs.bs_sleepduration = bs.bs_dtimperiod; 552 553 /* TSF out of range threshold fixed at 1 second */ 554 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; 555 556 ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); 557 ath_dbg(common, BEACON, 558 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", 559 bs.bs_bmissthreshold, bs.bs_sleepduration, 560 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); 561 562 /* Set the computed STA beacon timers */ 563 564 ath9k_hw_disable_interrupts(ah); 565 ath9k_hw_set_sta_beacon_timers(ah, &bs); 566 ah->imask |= ATH9K_INT_BMISS; 567 568 ath9k_hw_set_interrupts(ah); 569 ath9k_hw_enable_interrupts(ah); 570} 571 572static void ath9k_beacon_config_adhoc(struct ath_softc *sc, 573 struct ath_beacon_config *conf) 574{ 575 struct ath_hw *ah = sc->sc_ah; 576 struct ath_common *common = ath9k_hw_common(ah); 577 u32 intval, nexttbtt; 578 579 ath9k_reset_beacon_status(sc); 580 581 intval = TU_TO_USEC(conf->beacon_interval); 582 nexttbtt = intval; 583 584 if (conf->enable_beacon) 585 ah->imask |= ATH9K_INT_SWBA; 586 else 587 ah->imask &= ~ATH9K_INT_SWBA; 588 589 ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n", 590 nexttbtt, intval, conf->beacon_interval); 591 592 ath_beaconq_config(sc); 593 ath9k_beacon_init(sc, nexttbtt, intval); 594} 595 596bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) 597{ 598 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 599 struct ath_vif *avp = (void *)vif->drv_priv; 600 601 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 602 if ((vif->type != NL80211_IFTYPE_AP) || 603 (sc->nbcnvifs > 1)) { 604 ath_dbg(common, CONFIG, 605 "An AP interface is already present !\n"); 606 return false; 607 } 608 } 609 610 if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { 611 if ((vif->type == NL80211_IFTYPE_STATION) && 612 test_bit(SC_OP_BEACONS, &sc->sc_flags) && 613 !avp->primary_sta_vif) { 614 ath_dbg(common, CONFIG, 615 "Beacon already configured for a station interface\n"); 616 return false; 617 } 618 } 619 620 return true; 621} 622 623static void ath9k_cache_beacon_config(struct ath_softc *sc, 624 struct ieee80211_bss_conf *bss_conf) 625{ 626 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 627 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 628 629 ath_dbg(common, BEACON, 630 "Caching beacon data for BSS: %pM\n", bss_conf->bssid); 631 632 cur_conf->beacon_interval = bss_conf->beacon_int; 633 cur_conf->dtim_period = bss_conf->dtim_period; 634 cur_conf->listen_interval = 1; 635 cur_conf->dtim_count = 1; 636 cur_conf->bmiss_timeout = 637 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 638 639 /* 640 * It looks like mac80211 may end up using beacon interval of zero in 641 * some cases (at least for mesh point). Avoid getting into an 642 * infinite loop by using a bit safer value instead. To be safe, 643 * do sanity check on beacon interval for all operating modes. 644 */ 645 if (cur_conf->beacon_interval == 0) 646 cur_conf->beacon_interval = 100; 647 648 /* 649 * We don't parse dtim period from mac80211 during the driver 650 * initialization as it breaks association with hidden-ssid 651 * AP and it causes latency in roaming 652 */ 653 if (cur_conf->dtim_period == 0) 654 cur_conf->dtim_period = 1; 655 656} 657 658void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, 659 u32 changed) 660{ 661 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 662 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 663 664 if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { 665 ath9k_cache_beacon_config(sc, bss_conf); 666 ath9k_set_beacon(sc); 667 set_bit(SC_OP_BEACONS, &sc->sc_flags); 668 } else { 669 /* 670 * Take care of multiple interfaces when 671 * enabling/disabling SWBA. 672 */ 673 if (changed & BSS_CHANGED_BEACON_ENABLED) { 674 if (!bss_conf->enable_beacon && 675 (sc->nbcnvifs <= 1)) { 676 cur_conf->enable_beacon = false; 677 } else if (bss_conf->enable_beacon) { 678 cur_conf->enable_beacon = true; 679 ath9k_cache_beacon_config(sc, bss_conf); 680 } 681 } 682 683 if (cur_conf->beacon_interval) { 684 ath9k_set_beacon(sc); 685 686 if (cur_conf->enable_beacon) 687 set_bit(SC_OP_BEACONS, &sc->sc_flags); 688 else 689 clear_bit(SC_OP_BEACONS, &sc->sc_flags); 690 } 691 } 692} 693 694void ath9k_set_beacon(struct ath_softc *sc) 695{ 696 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 697 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 698 699 switch (sc->sc_ah->opmode) { 700 case NL80211_IFTYPE_AP: 701 ath9k_beacon_config_ap(sc, cur_conf); 702 break; 703 case NL80211_IFTYPE_ADHOC: 704 case NL80211_IFTYPE_MESH_POINT: 705 ath9k_beacon_config_adhoc(sc, cur_conf); 706 break; 707 case NL80211_IFTYPE_STATION: 708 ath9k_beacon_config_sta(sc, cur_conf); 709 break; 710 default: 711 ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); 712 return; 713 } 714} 715