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 21 void 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 65 static 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, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n", 171 intval, tsf, tsftu); 172 ath_dbg(common, ATH_DBG_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 186 static 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 (priv->op_flags & OP_TSF_RESET) { 211 ath9k_hw_reset_tsf(priv->ah); 212 priv->op_flags &= ~OP_TSF_RESET; 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 (priv->op_flags & OP_ENABLE_BEACON) 225 imask |= ATH9K_INT_SWBA; 226 227 ath_dbg(common, ATH_DBG_CONFIG, 228 "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " 229 "imask: 0x%x\n", 230 bss_conf->beacon_interval, nexttbtt, 231 priv->ah->config.sw_beacon_response_time, imask); 232 233 ath9k_htc_beaconq_config(priv); 234 235 WMI_CMD(WMI_DISABLE_INTR_CMDID); 236 ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); 237 priv->cur_beacon_conf.bmiss_cnt = 0; 238 htc_imask = cpu_to_be32(imask); 239 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 240 } 241 242 static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, 243 struct htc_beacon_config *bss_conf) 244 { 245 struct ath_common *common = ath9k_hw_common(priv->ah); 246 enum ath9k_int imask = 0; 247 u32 nexttbtt, intval, tsftu; 248 __be32 htc_imask = 0; 249 int ret __attribute__ ((unused)); 250 u8 cmd_rsp; 251 u64 tsf; 252 253 intval = bss_conf->beacon_interval; 254 nexttbtt = intval; 255 256 /* 257 * Pull nexttbtt forward to reflect the current TSF. 258 */ 259 tsf = ath9k_hw_gettsf64(priv->ah); 260 tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; 261 do { 262 nexttbtt += intval; 263 } while (nexttbtt < tsftu); 264 265 /* 266 * Only one IBSS interfce is allowed. 267 */ 268 if (intval > DEFAULT_SWBA_RESPONSE) 269 priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; 270 else 271 priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; 272 273 if (priv->op_flags & OP_ENABLE_BEACON) 274 imask |= ATH9K_INT_SWBA; 275 276 ath_dbg(common, ATH_DBG_CONFIG, 277 "IBSS Beacon config, intval: %d, nexttbtt: %u, " 278 "resp_time: %d, imask: 0x%x\n", 279 bss_conf->beacon_interval, nexttbtt, 280 priv->ah->config.sw_beacon_response_time, imask); 281 282 WMI_CMD(WMI_DISABLE_INTR_CMDID); 283 ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); 284 priv->cur_beacon_conf.bmiss_cnt = 0; 285 htc_imask = cpu_to_be32(imask); 286 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 287 } 288 289 void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, 290 enum htc_endpoint_id ep_id, bool txok) 291 { 292 dev_kfree_skb_any(skb); 293 } 294 295 static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, 296 int slot) 297 { 298 struct ath_common *common = ath9k_hw_common(priv->ah); 299 struct ieee80211_vif *vif; 300 struct sk_buff *skb; 301 struct ieee80211_hdr *hdr; 302 int padpos, padsize, ret, tx_slot; 303 304 spin_lock_bh(&priv->beacon_lock); 305 306 vif = priv->cur_beacon_conf.bslot[slot]; 307 308 skb = ieee80211_get_buffered_bc(priv->hw, vif); 309 310 while(skb) { 311 hdr = (struct ieee80211_hdr *) skb->data; 312 313 padpos = ath9k_cmn_padpos(hdr->frame_control); 314 padsize = padpos & 3; 315 if (padsize && skb->len > padpos) { 316 if (skb_headroom(skb) < padsize) { 317 dev_kfree_skb_any(skb); 318 goto next; 319 } 320 skb_push(skb, padsize); 321 memmove(skb->data, skb->data + padsize, padpos); 322 } 323 324 tx_slot = ath9k_htc_tx_get_slot(priv); 325 if (tx_slot < 0) { 326 ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); 327 dev_kfree_skb_any(skb); 328 goto next; 329 } 330 331 ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); 332 if (ret != 0) { 333 ath9k_htc_tx_clear_slot(priv, tx_slot); 334 dev_kfree_skb_any(skb); 335 336 ath_dbg(common, ATH_DBG_XMIT, 337 "Failed to send CAB frame\n"); 338 } else { 339 spin_lock_bh(&priv->tx.tx_lock); 340 priv->tx.queued_cnt++; 341 spin_unlock_bh(&priv->tx.tx_lock); 342 } 343 next: 344 skb = ieee80211_get_buffered_bc(priv->hw, vif); 345 } 346 347 spin_unlock_bh(&priv->beacon_lock); 348 } 349 350 static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, 351 int slot) 352 { 353 struct ath_common *common = ath9k_hw_common(priv->ah); 354 struct ieee80211_vif *vif; 355 struct ath9k_htc_vif *avp; 356 struct tx_beacon_header beacon_hdr; 357 struct ath9k_htc_tx_ctl *tx_ctl; 358 struct ieee80211_tx_info *info; 359 struct ieee80211_mgmt *mgmt; 360 struct sk_buff *beacon; 361 u8 *tx_fhdr; 362 int ret; 363 364 memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); 365 366 spin_lock_bh(&priv->beacon_lock); 367 368 vif = priv->cur_beacon_conf.bslot[slot]; 369 avp = (struct ath9k_htc_vif *)vif->drv_priv; 370 371 if (unlikely(priv->op_flags & OP_SCANNING)) { 372 spin_unlock_bh(&priv->beacon_lock); 373 return; 374 } 375 376 /* Get a new beacon */ 377 beacon = ieee80211_beacon_get(priv->hw, vif); 378 if (!beacon) { 379 spin_unlock_bh(&priv->beacon_lock); 380 return; 381 } 382 383 /* 384 * Update the TSF adjust value here, the HW will 385 * add this value for every beacon. 386 */ 387 mgmt = (struct ieee80211_mgmt *)beacon->data; 388 mgmt->u.beacon.timestamp = avp->tsfadjust; 389 390 info = IEEE80211_SKB_CB(beacon); 391 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 392 struct ieee80211_hdr *hdr = 393 (struct ieee80211_hdr *) beacon->data; 394 avp->seq_no += 0x10; 395 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 396 hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); 397 } 398 399 tx_ctl = HTC_SKB_CB(beacon); 400 memset(tx_ctl, 0, sizeof(*tx_ctl)); 401 402 tx_ctl->type = ATH9K_HTC_BEACON; 403 tx_ctl->epid = priv->beacon_ep; 404 405 beacon_hdr.vif_index = avp->index; 406 tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); 407 memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); 408 409 ret = htc_send(priv->htc, beacon); 410 if (ret != 0) { 411 if (ret == -ENOMEM) { 412 ath_dbg(common, ATH_DBG_BSTUCK, 413 "Failed to send beacon, no free TX buffer\n"); 414 } 415 dev_kfree_skb_any(beacon); 416 } 417 418 spin_unlock_bh(&priv->beacon_lock); 419 } 420 421 static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, 422 struct wmi_event_swba *swba) 423 { 424 struct ath_common *common = ath9k_hw_common(priv->ah); 425 u64 tsf; 426 u32 tsftu; 427 u16 intval; 428 int slot; 429 430 intval = priv->cur_beacon_conf.beacon_interval; 431 432 tsf = be64_to_cpu(swba->tsf); 433 tsftu = TSF_TO_TU(tsf >> 32, tsf); 434 slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; 435 slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; 436 437 ath_dbg(common, ATH_DBG_BEACON, 438 "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", 439 slot, tsf, tsftu, intval); 440 441 return slot; 442 } 443 444 void ath9k_htc_swba(struct ath9k_htc_priv *priv, 445 struct wmi_event_swba *swba) 446 { 447 struct ath_common *common = ath9k_hw_common(priv->ah); 448 int slot; 449 450 if (swba->beacon_pending != 0) { 451 priv->cur_beacon_conf.bmiss_cnt++; 452 if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { 453 ath_dbg(common, ATH_DBG_BSTUCK, 454 "Beacon stuck, HW reset\n"); 455 ieee80211_queue_work(priv->hw, 456 &priv->fatal_work); 457 } 458 return; 459 } 460 461 if (priv->cur_beacon_conf.bmiss_cnt) { 462 ath_dbg(common, ATH_DBG_BSTUCK, 463 "Resuming beacon xmit after %u misses\n", 464 priv->cur_beacon_conf.bmiss_cnt); 465 priv->cur_beacon_conf.bmiss_cnt = 0; 466 } 467 468 slot = ath9k_htc_choose_bslot(priv, swba); 469 spin_lock_bh(&priv->beacon_lock); 470 if (priv->cur_beacon_conf.bslot[slot] == NULL) { 471 spin_unlock_bh(&priv->beacon_lock); 472 return; 473 } 474 spin_unlock_bh(&priv->beacon_lock); 475 476 ath9k_htc_send_buffered(priv, slot); 477 ath9k_htc_send_beacon(priv, slot); 478 } 479 480 void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, 481 struct ieee80211_vif *vif) 482 { 483 struct ath_common *common = ath9k_hw_common(priv->ah); 484 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; 485 int i = 0; 486 487 spin_lock_bh(&priv->beacon_lock); 488 for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { 489 if (priv->cur_beacon_conf.bslot[i] == NULL) { 490 avp->bslot = i; 491 break; 492 } 493 } 494 495 priv->cur_beacon_conf.bslot[avp->bslot] = vif; 496 spin_unlock_bh(&priv->beacon_lock); 497 498 ath_dbg(common, ATH_DBG_CONFIG, 499 "Added interface at beacon slot: %d\n", avp->bslot); 500 } 501 502 void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, 503 struct ieee80211_vif *vif) 504 { 505 struct ath_common *common = ath9k_hw_common(priv->ah); 506 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; 507 508 spin_lock_bh(&priv->beacon_lock); 509 priv->cur_beacon_conf.bslot[avp->bslot] = NULL; 510 spin_unlock_bh(&priv->beacon_lock); 511 512 ath_dbg(common, ATH_DBG_CONFIG, 513 "Removed interface at beacon slot: %d\n", avp->bslot); 514 } 515 516 /* 517 * Calculate the TSF adjustment value for all slots 518 * other than zero. 519 */ 520 void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, 521 struct ieee80211_vif *vif) 522 { 523 struct ath_common *common = ath9k_hw_common(priv->ah); 524 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; 525 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 526 u64 tsfadjust; 527 528 if (avp->bslot == 0) 529 return; 530 531 /* 532 * The beacon interval cannot be different for multi-AP mode, 533 * and we reach here only for VIF slots greater than zero, 534 * so beacon_interval is guaranteed to be set in cur_conf. 535 */ 536 tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; 537 avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); 538 539 ath_dbg(common, ATH_DBG_CONFIG, 540 "tsfadjust is: %llu for bslot: %d\n", 541 (unsigned long long)tsfadjust, avp->bslot); 542 } 543 544 static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 545 { 546 bool *beacon_configured = (bool *)data; 547 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 548 549 if (vif->type == NL80211_IFTYPE_STATION && 550 avp->beacon_configured) 551 *beacon_configured = true; 552 } 553 554 static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, 555 struct ieee80211_vif *vif) 556 { 557 struct ath_common *common = ath9k_hw_common(priv->ah); 558 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 559 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 560 bool beacon_configured; 561 562 /* 563 * Changing the beacon interval when multiple AP interfaces 564 * are configured will affect beacon transmission of all 565 * of them. 566 */ 567 if ((priv->ah->opmode == NL80211_IFTYPE_AP) && 568 (priv->num_ap_vif > 1) && 569 (vif->type == NL80211_IFTYPE_AP) && 570 (cur_conf->beacon_interval != bss_conf->beacon_int)) { 571 ath_dbg(common, ATH_DBG_CONFIG, 572 "Changing beacon interval of multiple AP interfaces !\n"); 573 return false; 574 } 575 576 /* 577 * If the HW is operating in AP mode, any new station interfaces that 578 * are added cannot change the beacon parameters. 579 */ 580 if (priv->num_ap_vif && 581 (vif->type != NL80211_IFTYPE_AP)) { 582 ath_dbg(common, ATH_DBG_CONFIG, 583 "HW in AP mode, cannot set STA beacon parameters\n"); 584 return false; 585 } 586 587 /* 588 * The beacon parameters are configured only for the first 589 * station interface. 590 */ 591 if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && 592 (priv->num_sta_vif > 1) && 593 (vif->type == NL80211_IFTYPE_STATION)) { 594 beacon_configured = false; 595 ieee80211_iterate_active_interfaces_atomic(priv->hw, 596 ath9k_htc_beacon_iter, 597 &beacon_configured); 598 599 if (beacon_configured) { 600 ath_dbg(common, ATH_DBG_CONFIG, 601 "Beacon already configured for a station interface\n"); 602 return false; 603 } 604 } 605 606 return true; 607 } 608 609 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, 610 struct ieee80211_vif *vif) 611 { 612 struct ath_common *common = ath9k_hw_common(priv->ah); 613 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 614 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 615 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 616 617 if (!ath9k_htc_check_beacon_config(priv, vif)) 618 return; 619 620 cur_conf->beacon_interval = bss_conf->beacon_int; 621 if (cur_conf->beacon_interval == 0) 622 cur_conf->beacon_interval = 100; 623 624 cur_conf->dtim_period = bss_conf->dtim_period; 625 cur_conf->bmiss_timeout = 626 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 627 628 switch (vif->type) { 629 case NL80211_IFTYPE_STATION: 630 ath9k_htc_beacon_config_sta(priv, cur_conf); 631 avp->beacon_configured = true; 632 break; 633 case NL80211_IFTYPE_ADHOC: 634 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 635 break; 636 case NL80211_IFTYPE_AP: 637 ath9k_htc_beacon_config_ap(priv, cur_conf); 638 break; 639 default: 640 ath_dbg(common, ATH_DBG_CONFIG, 641 "Unsupported beaconing mode\n"); 642 return; 643 } 644 } 645 646 void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) 647 { 648 struct ath_common *common = ath9k_hw_common(priv->ah); 649 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 650 651 switch (priv->ah->opmode) { 652 case NL80211_IFTYPE_STATION: 653 ath9k_htc_beacon_config_sta(priv, cur_conf); 654 break; 655 case NL80211_IFTYPE_ADHOC: 656 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 657 break; 658 case NL80211_IFTYPE_AP: 659 ath9k_htc_beacon_config_ap(priv, cur_conf); 660 break; 661 default: 662 ath_dbg(common, ATH_DBG_CONFIG, 663 "Unsupported beaconing mode\n"); 664 return; 665 } 666 } 667