htc_drv_beacon.c revision 8b2c98243e8d00f9c6b6059976d6de51491ee0c7
1/* 2 * Copyright (c) 2010-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 "htc.h" 18 19#define FUDGE 2 20 21void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) 22{ 23 struct ath_hw *ah = priv->ah; 24 struct ath9k_tx_queue_info qi, qi_be; 25 26 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); 27 memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); 28 29 ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); 30 31 if (priv->ah->opmode == NL80211_IFTYPE_AP) { 32 qi.tqi_aifs = 1; 33 qi.tqi_cwmin = 0; 34 qi.tqi_cwmax = 0; 35 } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { 36 int qnum = priv->hwq_map[WME_AC_BE]; 37 38 ath9k_hw_get_txq_props(ah, qnum, &qi_be); 39 40 qi.tqi_aifs = qi_be.tqi_aifs; 41 42 /* 43 * For WIFI Beacon Distribution 44 * Long slot time : 2x cwmin 45 * Short slot time : 4x cwmin 46 */ 47 if (ah->slottime == ATH9K_SLOT_TIME_20) 48 qi.tqi_cwmin = 2*qi_be.tqi_cwmin; 49 else 50 qi.tqi_cwmin = 4*qi_be.tqi_cwmin; 51 52 qi.tqi_cwmax = qi_be.tqi_cwmax; 53 54 } 55 56 if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { 57 ath_err(ath9k_hw_common(ah), 58 "Unable to update beacon queue %u!\n", priv->beaconq); 59 } else { 60 ath9k_hw_resettxqueue(ah, priv->beaconq); 61 } 62} 63 64 65static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, 66 struct htc_beacon_config *bss_conf) 67{ 68 struct ath_common *common = ath9k_hw_common(priv->ah); 69 struct ath9k_beacon_state bs; 70 enum ath9k_int imask = 0; 71 int dtimperiod, dtimcount, sleepduration; 72 int cfpperiod, cfpcount, bmiss_timeout; 73 u32 nexttbtt = 0, intval, tsftu; 74 __be32 htc_imask = 0; 75 u64 tsf; 76 int num_beacons, offset, dtim_dec_count, cfp_dec_count; 77 int ret __attribute__ ((unused)); 78 u8 cmd_rsp; 79 80 memset(&bs, 0, sizeof(bs)); 81 82 intval = bss_conf->beacon_interval; 83 bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); 84 85 /* 86 * Setup dtim and cfp parameters according to 87 * last beacon we received (which may be none). 88 */ 89 dtimperiod = bss_conf->dtim_period; 90 if (dtimperiod <= 0) /* NB: 0 if not known */ 91 dtimperiod = 1; 92 dtimcount = 1; 93 if (dtimcount >= dtimperiod) /* NB: sanity check */ 94 dtimcount = 0; 95 cfpperiod = 1; /* NB: no PCF support yet */ 96 cfpcount = 0; 97 98 sleepduration = intval; 99 if (sleepduration <= 0) 100 sleepduration = intval; 101 102 /* 103 * Pull nexttbtt forward to reflect the current 104 * TSF and calculate dtim+cfp state for the result. 105 */ 106 tsf = ath9k_hw_gettsf64(priv->ah); 107 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 108 109 num_beacons = tsftu / intval + 1; 110 offset = tsftu % intval; 111 nexttbtt = tsftu - offset; 112 if (offset) 113 nexttbtt += intval; 114 115 /* DTIM Beacon every dtimperiod Beacon */ 116 dtim_dec_count = num_beacons % dtimperiod; 117 /* CFP every cfpperiod DTIM Beacon */ 118 cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; 119 if (dtim_dec_count) 120 cfp_dec_count++; 121 122 dtimcount -= dtim_dec_count; 123 if (dtimcount < 0) 124 dtimcount += dtimperiod; 125 126 cfpcount -= cfp_dec_count; 127 if (cfpcount < 0) 128 cfpcount += cfpperiod; 129 130 bs.bs_intval = intval; 131 bs.bs_nexttbtt = nexttbtt; 132 bs.bs_dtimperiod = dtimperiod*intval; 133 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; 134 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; 135 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; 136 bs.bs_cfpmaxduration = 0; 137 138 /* 139 * Calculate the number of consecutive beacons to miss* before taking 140 * a BMISS interrupt. The configuration is specified in TU so we only 141 * need calculate based on the beacon interval. Note that we clamp the 142 * result to at most 15 beacons. 143 */ 144 if (sleepduration > intval) { 145 bs.bs_bmissthreshold = ATH_DEFAULT_BMISS_LIMIT / 2; 146 } else { 147 bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); 148 if (bs.bs_bmissthreshold > 15) 149 bs.bs_bmissthreshold = 15; 150 else if (bs.bs_bmissthreshold <= 0) 151 bs.bs_bmissthreshold = 1; 152 } 153 154 /* 155 * Calculate sleep duration. The configuration is given in ms. 156 * We ensure a multiple of the beacon period is used. Also, if the sleep 157 * duration is greater than the DTIM period then it makes senses 158 * to make it a multiple of that. 159 * 160 * XXX fixed at 100ms 161 */ 162 163 bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); 164 if (bs.bs_sleepduration > bs.bs_dtimperiod) 165 bs.bs_sleepduration = bs.bs_dtimperiod; 166 167 /* TSF out of range threshold fixed at 1 second */ 168 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; 169 170 ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n", 171 intval, tsf, tsftu); 172 ath_dbg(common, CONFIG, 173 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", 174 bs.bs_bmissthreshold, bs.bs_sleepduration, 175 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); 176 177 /* Set the computed STA beacon timers */ 178 179 WMI_CMD(WMI_DISABLE_INTR_CMDID); 180 ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); 181 imask |= ATH9K_INT_BMISS; 182 htc_imask = cpu_to_be32(imask); 183 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 184} 185 186static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, 187 struct htc_beacon_config *bss_conf) 188{ 189 struct ath_common *common = ath9k_hw_common(priv->ah); 190 enum ath9k_int imask = 0; 191 u32 nexttbtt, intval, tsftu; 192 __be32 htc_imask = 0; 193 int ret __attribute__ ((unused)); 194 u8 cmd_rsp; 195 u64 tsf; 196 197 intval = bss_conf->beacon_interval; 198 intval /= ATH9K_HTC_MAX_BCN_VIF; 199 nexttbtt = intval; 200 201 /* 202 * To reduce beacon misses under heavy TX load, 203 * set the beacon response time to a larger value. 204 */ 205 if (intval > DEFAULT_SWBA_RESPONSE) 206 priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; 207 else 208 priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; 209 210 if (test_bit(OP_TSF_RESET, &priv->op_flags)) { 211 ath9k_hw_reset_tsf(priv->ah); 212 clear_bit(OP_TSF_RESET, &priv->op_flags); 213 } else { 214 /* 215 * Pull nexttbtt forward to reflect the current TSF. 216 */ 217 tsf = ath9k_hw_gettsf64(priv->ah); 218 tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; 219 do { 220 nexttbtt += intval; 221 } while (nexttbtt < tsftu); 222 } 223 224 if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) 225 imask |= ATH9K_INT_SWBA; 226 227 ath_dbg(common, CONFIG, 228 "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d imask: 0x%x\n", 229 bss_conf->beacon_interval, nexttbtt, 230 priv->ah->config.sw_beacon_response_time, imask); 231 232 ath9k_htc_beaconq_config(priv); 233 234 WMI_CMD(WMI_DISABLE_INTR_CMDID); 235 ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); 236 priv->cur_beacon_conf.bmiss_cnt = 0; 237 htc_imask = cpu_to_be32(imask); 238 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 239} 240 241static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, 242 struct htc_beacon_config *bss_conf) 243{ 244 struct ath_common *common = ath9k_hw_common(priv->ah); 245 enum ath9k_int imask = 0; 246 u32 nexttbtt, intval, tsftu; 247 __be32 htc_imask = 0; 248 int ret __attribute__ ((unused)); 249 u8 cmd_rsp; 250 u64 tsf; 251 252 intval = bss_conf->beacon_interval; 253 nexttbtt = intval; 254 255 /* 256 * Pull nexttbtt forward to reflect the current TSF. 257 */ 258 tsf = ath9k_hw_gettsf64(priv->ah); 259 tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; 260 do { 261 nexttbtt += intval; 262 } while (nexttbtt < tsftu); 263 264 /* 265 * Only one IBSS interfce is allowed. 266 */ 267 if (intval > DEFAULT_SWBA_RESPONSE) 268 priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; 269 else 270 priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; 271 272 if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) 273 imask |= ATH9K_INT_SWBA; 274 275 ath_dbg(common, CONFIG, 276 "IBSS Beacon config, intval: %d, nexttbtt: %u, resp_time: %d, imask: 0x%x\n", 277 bss_conf->beacon_interval, nexttbtt, 278 priv->ah->config.sw_beacon_response_time, imask); 279 280 WMI_CMD(WMI_DISABLE_INTR_CMDID); 281 ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); 282 priv->cur_beacon_conf.bmiss_cnt = 0; 283 htc_imask = cpu_to_be32(imask); 284 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 285} 286 287void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, 288 enum htc_endpoint_id ep_id, bool txok) 289{ 290 dev_kfree_skb_any(skb); 291} 292 293static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, 294 int slot) 295{ 296 struct ath_common *common = ath9k_hw_common(priv->ah); 297 struct ieee80211_vif *vif; 298 struct sk_buff *skb; 299 struct ieee80211_hdr *hdr; 300 int padpos, padsize, ret, tx_slot; 301 302 spin_lock_bh(&priv->beacon_lock); 303 304 vif = priv->cur_beacon_conf.bslot[slot]; 305 306 skb = ieee80211_get_buffered_bc(priv->hw, vif); 307 308 while(skb) { 309 hdr = (struct ieee80211_hdr *) skb->data; 310 311 padpos = ath9k_cmn_padpos(hdr->frame_control); 312 padsize = padpos & 3; 313 if (padsize && skb->len > padpos) { 314 if (skb_headroom(skb) < padsize) { 315 dev_kfree_skb_any(skb); 316 goto next; 317 } 318 skb_push(skb, padsize); 319 memmove(skb->data, skb->data + padsize, padpos); 320 } 321 322 tx_slot = ath9k_htc_tx_get_slot(priv); 323 if (tx_slot < 0) { 324 ath_dbg(common, XMIT, "No free CAB slot\n"); 325 dev_kfree_skb_any(skb); 326 goto next; 327 } 328 329 ret = ath9k_htc_tx_start(priv, NULL, skb, tx_slot, true); 330 if (ret != 0) { 331 ath9k_htc_tx_clear_slot(priv, tx_slot); 332 dev_kfree_skb_any(skb); 333 334 ath_dbg(common, XMIT, "Failed to send CAB frame\n"); 335 } else { 336 spin_lock_bh(&priv->tx.tx_lock); 337 priv->tx.queued_cnt++; 338 spin_unlock_bh(&priv->tx.tx_lock); 339 } 340 next: 341 skb = ieee80211_get_buffered_bc(priv->hw, vif); 342 } 343 344 spin_unlock_bh(&priv->beacon_lock); 345} 346 347static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, 348 int slot) 349{ 350 struct ath_common *common = ath9k_hw_common(priv->ah); 351 struct ieee80211_vif *vif; 352 struct ath9k_htc_vif *avp; 353 struct tx_beacon_header beacon_hdr; 354 struct ath9k_htc_tx_ctl *tx_ctl; 355 struct ieee80211_tx_info *info; 356 struct ieee80211_mgmt *mgmt; 357 struct sk_buff *beacon; 358 u8 *tx_fhdr; 359 int ret; 360 361 memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); 362 363 spin_lock_bh(&priv->beacon_lock); 364 365 vif = priv->cur_beacon_conf.bslot[slot]; 366 avp = (struct ath9k_htc_vif *)vif->drv_priv; 367 368 if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) { 369 spin_unlock_bh(&priv->beacon_lock); 370 return; 371 } 372 373 /* Get a new beacon */ 374 beacon = ieee80211_beacon_get(priv->hw, vif); 375 if (!beacon) { 376 spin_unlock_bh(&priv->beacon_lock); 377 return; 378 } 379 380 /* 381 * Update the TSF adjust value here, the HW will 382 * add this value for every beacon. 383 */ 384 mgmt = (struct ieee80211_mgmt *)beacon->data; 385 mgmt->u.beacon.timestamp = avp->tsfadjust; 386 387 info = IEEE80211_SKB_CB(beacon); 388 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 389 struct ieee80211_hdr *hdr = 390 (struct ieee80211_hdr *) beacon->data; 391 avp->seq_no += 0x10; 392 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 393 hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); 394 } 395 396 tx_ctl = HTC_SKB_CB(beacon); 397 memset(tx_ctl, 0, sizeof(*tx_ctl)); 398 399 tx_ctl->type = ATH9K_HTC_BEACON; 400 tx_ctl->epid = priv->beacon_ep; 401 402 beacon_hdr.vif_index = avp->index; 403 tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); 404 memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); 405 406 ret = htc_send(priv->htc, beacon); 407 if (ret != 0) { 408 if (ret == -ENOMEM) { 409 ath_dbg(common, BSTUCK, 410 "Failed to send beacon, no free TX buffer\n"); 411 } 412 dev_kfree_skb_any(beacon); 413 } 414 415 spin_unlock_bh(&priv->beacon_lock); 416} 417 418static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, 419 struct wmi_event_swba *swba) 420{ 421 struct ath_common *common = ath9k_hw_common(priv->ah); 422 u64 tsf; 423 u32 tsftu; 424 u16 intval; 425 int slot; 426 427 intval = priv->cur_beacon_conf.beacon_interval; 428 429 tsf = be64_to_cpu(swba->tsf); 430 tsftu = TSF_TO_TU(tsf >> 32, tsf); 431 slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; 432 slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; 433 434 ath_dbg(common, BEACON, 435 "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", 436 slot, tsf, tsftu, intval); 437 438 return slot; 439} 440 441void ath9k_htc_swba(struct ath9k_htc_priv *priv, 442 struct wmi_event_swba *swba) 443{ 444 struct ath_common *common = ath9k_hw_common(priv->ah); 445 int slot; 446 447 if (swba->beacon_pending != 0) { 448 priv->cur_beacon_conf.bmiss_cnt++; 449 if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { 450 ath_dbg(common, BSTUCK, "Beacon stuck, HW reset\n"); 451 ieee80211_queue_work(priv->hw, 452 &priv->fatal_work); 453 } 454 return; 455 } 456 457 if (priv->cur_beacon_conf.bmiss_cnt) { 458 ath_dbg(common, BSTUCK, 459 "Resuming beacon xmit after %u misses\n", 460 priv->cur_beacon_conf.bmiss_cnt); 461 priv->cur_beacon_conf.bmiss_cnt = 0; 462 } 463 464 slot = ath9k_htc_choose_bslot(priv, swba); 465 spin_lock_bh(&priv->beacon_lock); 466 if (priv->cur_beacon_conf.bslot[slot] == NULL) { 467 spin_unlock_bh(&priv->beacon_lock); 468 return; 469 } 470 spin_unlock_bh(&priv->beacon_lock); 471 472 ath9k_htc_send_buffered(priv, slot); 473 ath9k_htc_send_beacon(priv, slot); 474} 475 476void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, 477 struct ieee80211_vif *vif) 478{ 479 struct ath_common *common = ath9k_hw_common(priv->ah); 480 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; 481 int i = 0; 482 483 spin_lock_bh(&priv->beacon_lock); 484 for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { 485 if (priv->cur_beacon_conf.bslot[i] == NULL) { 486 avp->bslot = i; 487 break; 488 } 489 } 490 491 priv->cur_beacon_conf.bslot[avp->bslot] = vif; 492 spin_unlock_bh(&priv->beacon_lock); 493 494 ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", 495 avp->bslot); 496} 497 498void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, 499 struct ieee80211_vif *vif) 500{ 501 struct ath_common *common = ath9k_hw_common(priv->ah); 502 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; 503 504 spin_lock_bh(&priv->beacon_lock); 505 priv->cur_beacon_conf.bslot[avp->bslot] = NULL; 506 spin_unlock_bh(&priv->beacon_lock); 507 508 ath_dbg(common, CONFIG, "Removed interface at beacon slot: %d\n", 509 avp->bslot); 510} 511 512/* 513 * Calculate the TSF adjustment value for all slots 514 * other than zero. 515 */ 516void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, 517 struct ieee80211_vif *vif) 518{ 519 struct ath_common *common = ath9k_hw_common(priv->ah); 520 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; 521 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 522 u64 tsfadjust; 523 524 if (avp->bslot == 0) 525 return; 526 527 /* 528 * The beacon interval cannot be different for multi-AP mode, 529 * and we reach here only for VIF slots greater than zero, 530 * so beacon_interval is guaranteed to be set in cur_conf. 531 */ 532 tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; 533 avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); 534 535 ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n", 536 (unsigned long long)tsfadjust, avp->bslot); 537} 538 539static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 540{ 541 bool *beacon_configured = (bool *)data; 542 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 543 544 if (vif->type == NL80211_IFTYPE_STATION && 545 avp->beacon_configured) 546 *beacon_configured = true; 547} 548 549static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, 550 struct ieee80211_vif *vif) 551{ 552 struct ath_common *common = ath9k_hw_common(priv->ah); 553 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 554 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 555 bool beacon_configured; 556 557 /* 558 * Changing the beacon interval when multiple AP interfaces 559 * are configured will affect beacon transmission of all 560 * of them. 561 */ 562 if ((priv->ah->opmode == NL80211_IFTYPE_AP) && 563 (priv->num_ap_vif > 1) && 564 (vif->type == NL80211_IFTYPE_AP) && 565 (cur_conf->beacon_interval != bss_conf->beacon_int)) { 566 ath_dbg(common, CONFIG, 567 "Changing beacon interval of multiple AP interfaces !\n"); 568 return false; 569 } 570 571 /* 572 * If the HW is operating in AP mode, any new station interfaces that 573 * are added cannot change the beacon parameters. 574 */ 575 if (priv->num_ap_vif && 576 (vif->type != NL80211_IFTYPE_AP)) { 577 ath_dbg(common, CONFIG, 578 "HW in AP mode, cannot set STA beacon parameters\n"); 579 return false; 580 } 581 582 /* 583 * The beacon parameters are configured only for the first 584 * station interface. 585 */ 586 if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && 587 (priv->num_sta_vif > 1) && 588 (vif->type == NL80211_IFTYPE_STATION)) { 589 beacon_configured = false; 590 ieee80211_iterate_active_interfaces_atomic( 591 priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL, 592 ath9k_htc_beacon_iter, &beacon_configured); 593 594 if (beacon_configured) { 595 ath_dbg(common, CONFIG, 596 "Beacon already configured for a station interface\n"); 597 return false; 598 } 599 } 600 601 return true; 602} 603 604void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, 605 struct ieee80211_vif *vif) 606{ 607 struct ath_common *common = ath9k_hw_common(priv->ah); 608 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 609 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 610 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 611 612 if (!ath9k_htc_check_beacon_config(priv, vif)) 613 return; 614 615 cur_conf->beacon_interval = bss_conf->beacon_int; 616 if (cur_conf->beacon_interval == 0) 617 cur_conf->beacon_interval = 100; 618 619 cur_conf->dtim_period = bss_conf->dtim_period; 620 cur_conf->bmiss_timeout = 621 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 622 623 switch (vif->type) { 624 case NL80211_IFTYPE_STATION: 625 ath9k_htc_beacon_config_sta(priv, cur_conf); 626 avp->beacon_configured = true; 627 break; 628 case NL80211_IFTYPE_ADHOC: 629 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 630 break; 631 case NL80211_IFTYPE_AP: 632 ath9k_htc_beacon_config_ap(priv, cur_conf); 633 break; 634 default: 635 ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); 636 return; 637 } 638} 639 640void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) 641{ 642 struct ath_common *common = ath9k_hw_common(priv->ah); 643 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 644 645 switch (priv->ah->opmode) { 646 case NL80211_IFTYPE_STATION: 647 ath9k_htc_beacon_config_sta(priv, cur_conf); 648 break; 649 case NL80211_IFTYPE_ADHOC: 650 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 651 break; 652 case NL80211_IFTYPE_AP: 653 ath9k_htc_beacon_config_ap(priv, cur_conf); 654 break; 655 default: 656 ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); 657 return; 658 } 659} 660