0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/dma-mapping.h>
0018 #include "ath9k.h"
0019
0020 #define FUDGE 2
0021
0022 static void ath9k_reset_beacon_status(struct ath_softc *sc)
0023 {
0024 sc->beacon.tx_processed = false;
0025 sc->beacon.tx_last = false;
0026 }
0027
0028
0029
0030
0031
0032
0033 static void ath9k_beaconq_config(struct ath_softc *sc)
0034 {
0035 struct ath_hw *ah = sc->sc_ah;
0036 struct ath_common *common = ath9k_hw_common(ah);
0037 struct ath9k_tx_queue_info qi, qi_be;
0038 struct ath_txq *txq;
0039
0040 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
0041
0042 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
0043 sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
0044
0045 qi.tqi_aifs = 1;
0046 qi.tqi_cwmin = 0;
0047 qi.tqi_cwmax = 0;
0048 } else {
0049
0050 txq = sc->tx.txq_map[IEEE80211_AC_BE];
0051 ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
0052 qi.tqi_aifs = qi_be.tqi_aifs;
0053 if (ah->slottime == 20)
0054 qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
0055 else
0056 qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
0057 qi.tqi_cwmax = qi_be.tqi_cwmax;
0058 }
0059
0060 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
0061 ath_err(common, "Unable to update h/w beacon queue parameters\n");
0062 } else {
0063 ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
0064 }
0065 }
0066
0067
0068
0069
0070
0071
0072 static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
0073 struct ath_buf *bf, int rateidx)
0074 {
0075 struct sk_buff *skb = bf->bf_mpdu;
0076 struct ath_hw *ah = sc->sc_ah;
0077 struct ath_common *common = ath9k_hw_common(ah);
0078 struct ath_tx_info info;
0079 struct ieee80211_supported_band *sband;
0080 u8 chainmask = ah->txchainmask;
0081 u8 i, rate = 0;
0082
0083 sband = &common->sbands[sc->cur_chandef.chan->band];
0084 rate = sband->bitrates[rateidx].hw_value;
0085 if (vif->bss_conf.use_short_preamble)
0086 rate |= sband->bitrates[rateidx].hw_value_short;
0087
0088 memset(&info, 0, sizeof(info));
0089 info.pkt_len = skb->len + FCS_LEN;
0090 info.type = ATH9K_PKT_TYPE_BEACON;
0091 for (i = 0; i < 4; i++)
0092 info.txpower[i] = MAX_RATE_POWER;
0093 info.keyix = ATH9K_TXKEYIX_INVALID;
0094 info.keytype = ATH9K_KEY_TYPE_CLEAR;
0095 info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK;
0096
0097 info.buf_addr[0] = bf->bf_buf_addr;
0098 info.buf_len[0] = roundup(skb->len, 4);
0099
0100 info.is_first = true;
0101 info.is_last = true;
0102
0103 info.qcu = sc->beacon.beaconq;
0104
0105 info.rates[0].Tries = 1;
0106 info.rates[0].Rate = rate;
0107 info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
0108
0109 ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
0110 }
0111
0112 static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
0113 struct ieee80211_vif *vif)
0114 {
0115 struct ath_softc *sc = hw->priv;
0116 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0117 struct ath_buf *bf;
0118 struct ath_vif *avp = (void *)vif->drv_priv;
0119 struct sk_buff *skb;
0120 struct ath_txq *cabq = sc->beacon.cabq;
0121 struct ieee80211_tx_info *info;
0122 struct ieee80211_mgmt *mgmt_hdr;
0123 int cabq_depth;
0124
0125 if (avp->av_bcbuf == NULL)
0126 return NULL;
0127
0128 bf = avp->av_bcbuf;
0129 skb = bf->bf_mpdu;
0130 if (skb) {
0131 dma_unmap_single(sc->dev, bf->bf_buf_addr,
0132 skb->len, DMA_TO_DEVICE);
0133 dev_kfree_skb_any(skb);
0134 bf->bf_buf_addr = 0;
0135 bf->bf_mpdu = NULL;
0136 }
0137
0138 skb = ieee80211_beacon_get(hw, vif, 0);
0139 if (skb == NULL)
0140 return NULL;
0141
0142 bf->bf_mpdu = skb;
0143
0144 mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
0145 mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
0146
0147 info = IEEE80211_SKB_CB(skb);
0148
0149 ath_assign_seq(common, skb);
0150
0151
0152 if (ath9k_is_chanctx_enabled())
0153 ath9k_beacon_add_noa(sc, avp, skb);
0154
0155 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
0156 skb->len, DMA_TO_DEVICE);
0157 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
0158 dev_kfree_skb_any(skb);
0159 bf->bf_mpdu = NULL;
0160 bf->bf_buf_addr = 0;
0161 ath_err(common, "dma_mapping_error on beaconing\n");
0162 return NULL;
0163 }
0164
0165 skb = ieee80211_get_buffered_bc(hw, vif);
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 spin_lock_bh(&cabq->axq_lock);
0176 cabq_depth = cabq->axq_depth;
0177 spin_unlock_bh(&cabq->axq_lock);
0178
0179 if (skb && cabq_depth) {
0180 if (sc->cur_chan->nvifs > 1) {
0181 ath_dbg(common, BEACON,
0182 "Flushing previous cabq traffic\n");
0183 ath_draintxq(sc, cabq);
0184 }
0185 }
0186
0187 ath9k_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
0188
0189 if (skb)
0190 ath_tx_cabq(hw, vif, skb);
0191
0192 return bf;
0193 }
0194
0195 void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
0196 {
0197 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0198 struct ath_vif *avp = (void *)vif->drv_priv;
0199 int slot;
0200
0201 avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list);
0202 list_del(&avp->av_bcbuf->list);
0203
0204 for (slot = 0; slot < ATH_BCBUF; slot++) {
0205 if (sc->beacon.bslot[slot] == NULL) {
0206 avp->av_bslot = slot;
0207 break;
0208 }
0209 }
0210
0211 sc->beacon.bslot[avp->av_bslot] = vif;
0212
0213 ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
0214 avp->av_bslot);
0215 }
0216
0217 void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
0218 {
0219 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0220 struct ath_vif *avp = (void *)vif->drv_priv;
0221 struct ath_buf *bf = avp->av_bcbuf;
0222
0223 ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
0224 avp->av_bslot);
0225
0226 tasklet_disable(&sc->bcon_tasklet);
0227
0228 if (bf && bf->bf_mpdu) {
0229 struct sk_buff *skb = bf->bf_mpdu;
0230 dma_unmap_single(sc->dev, bf->bf_buf_addr,
0231 skb->len, DMA_TO_DEVICE);
0232 dev_kfree_skb_any(skb);
0233 bf->bf_mpdu = NULL;
0234 bf->bf_buf_addr = 0;
0235 }
0236
0237 avp->av_bcbuf = NULL;
0238 sc->beacon.bslot[avp->av_bslot] = NULL;
0239 list_add_tail(&bf->list, &sc->beacon.bbuf);
0240
0241 tasklet_enable(&sc->bcon_tasklet);
0242 }
0243
0244 void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc)
0245 {
0246 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0247 struct ieee80211_vif *vif;
0248 struct ath_vif *avp;
0249 s64 tsfadjust;
0250 u32 offset;
0251 int first_slot = ATH_BCBUF;
0252 int slot;
0253
0254 tasklet_disable_in_atomic(&sc->bcon_tasklet);
0255
0256
0257 for (slot = 0; slot < ATH_BCBUF; slot++) {
0258 if (sc->beacon.bslot[slot]) {
0259 first_slot = slot;
0260 break;
0261 }
0262 }
0263 if (first_slot == 0)
0264 goto out;
0265
0266
0267 for (slot = 0; slot < ATH_BCBUF; slot++) {
0268 if (slot + first_slot < ATH_BCBUF) {
0269 vif = sc->beacon.bslot[slot + first_slot];
0270 sc->beacon.bslot[slot] = vif;
0271
0272 if (vif) {
0273 avp = (void *)vif->drv_priv;
0274 avp->av_bslot = slot;
0275 }
0276 } else {
0277 sc->beacon.bslot[slot] = NULL;
0278 }
0279 }
0280
0281 vif = sc->beacon.bslot[0];
0282 if (WARN_ON(!vif))
0283 goto out;
0284
0285
0286 avp = (void *)vif->drv_priv;
0287 tsfadjust = le64_to_cpu(avp->tsf_adjust);
0288
0289 ath_dbg(common, CONFIG,
0290 "Adjusting global TSF after beacon slot reassignment: %lld\n",
0291 (signed long long)tsfadjust);
0292
0293
0294 avp->chanctx->tsf_val += tsfadjust;
0295 if (sc->cur_chan == avp->chanctx) {
0296 offset = ath9k_hw_get_tsf_offset(&avp->chanctx->tsf_ts, NULL);
0297 ath9k_hw_settsf64(sc->sc_ah, avp->chanctx->tsf_val + offset);
0298 }
0299
0300
0301
0302 out:
0303 tasklet_enable(&sc->bcon_tasklet);
0304 }
0305
0306 static int ath9k_beacon_choose_slot(struct ath_softc *sc)
0307 {
0308 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0309 struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
0310 u16 intval;
0311 u32 tsftu;
0312 u64 tsf;
0313 int slot;
0314
0315 if (sc->sc_ah->opmode != NL80211_IFTYPE_AP &&
0316 sc->sc_ah->opmode != NL80211_IFTYPE_MESH_POINT) {
0317 ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
0318 ath9k_hw_gettsf64(sc->sc_ah));
0319 return 0;
0320 }
0321
0322 intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
0323 tsf = ath9k_hw_gettsf64(sc->sc_ah);
0324 tsf += TU_TO_USEC(sc->sc_ah->config.sw_beacon_response_time);
0325 tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
0326 slot = (tsftu % (intval * ATH_BCBUF)) / intval;
0327
0328 ath_dbg(common, BEACON, "slot: %d tsf: %llu tsftu: %u\n",
0329 slot, tsf, tsftu / ATH_BCBUF);
0330
0331 return slot;
0332 }
0333
0334 static void ath9k_set_tsfadjust(struct ath_softc *sc,
0335 struct ath_beacon_config *cur_conf)
0336 {
0337 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0338 s64 tsfadjust;
0339 int slot;
0340
0341 for (slot = 0; slot < ATH_BCBUF; slot++) {
0342 struct ath_vif *avp;
0343
0344 if (!sc->beacon.bslot[slot])
0345 continue;
0346
0347 avp = (void *)sc->beacon.bslot[slot]->drv_priv;
0348
0349
0350
0351
0352
0353
0354 tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
0355 tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
0356 avp->tsf_adjust = cpu_to_le64(tsfadjust);
0357
0358 ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
0359 (signed long long)tsfadjust, avp->av_bslot);
0360 }
0361 }
0362
0363 bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
0364 {
0365 if (!vif || !vif->bss_conf.csa_active)
0366 return false;
0367
0368 if (!ieee80211_beacon_cntdwn_is_complete(vif))
0369 return false;
0370
0371 ieee80211_csa_finish(vif);
0372 return true;
0373 }
0374
0375 static void ath9k_csa_update_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
0376 {
0377 struct ath_softc *sc = data;
0378 ath9k_csa_is_finished(sc, vif);
0379 }
0380
0381 void ath9k_csa_update(struct ath_softc *sc)
0382 {
0383 ieee80211_iterate_active_interfaces_atomic(sc->hw,
0384 IEEE80211_IFACE_ITER_NORMAL,
0385 ath9k_csa_update_vif, sc);
0386 }
0387
0388 void ath9k_beacon_tasklet(struct tasklet_struct *t)
0389 {
0390 struct ath_softc *sc = from_tasklet(sc, t, bcon_tasklet);
0391 struct ath_hw *ah = sc->sc_ah;
0392 struct ath_common *common = ath9k_hw_common(ah);
0393 struct ath_buf *bf = NULL;
0394 struct ieee80211_vif *vif;
0395 bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
0396 int slot;
0397
0398 if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
0399 ath_dbg(common, RESET,
0400 "reset work is pending, skip beaconing now\n");
0401 return;
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411 if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
0412 sc->beacon.bmisscnt++;
0413
0414 ath9k_hw_check_nav(ah);
0415
0416
0417
0418
0419
0420
0421
0422 if (!ath_hw_check(sc))
0423 return;
0424
0425 if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
0426 ath_dbg(common, BSTUCK,
0427 "missed %u consecutive beacons\n",
0428 sc->beacon.bmisscnt);
0429 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
0430 if (sc->beacon.bmisscnt > 3)
0431 ath9k_hw_bstuck_nfcal(ah);
0432 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
0433 ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
0434 sc->beacon.bmisscnt = 0;
0435 ath9k_queue_reset(sc, RESET_TYPE_BEACON_STUCK);
0436 }
0437
0438 return;
0439 }
0440
0441 slot = ath9k_beacon_choose_slot(sc);
0442 vif = sc->beacon.bslot[slot];
0443
0444
0445 if (!edma) {
0446 if (ath9k_is_chanctx_enabled()) {
0447 ath_chanctx_beacon_sent_ev(sc,
0448 ATH_CHANCTX_EVENT_BEACON_SENT);
0449 }
0450
0451 if (ath9k_csa_is_finished(sc, vif))
0452 return;
0453 }
0454
0455 if (!vif || !vif->bss_conf.enable_beacon)
0456 return;
0457
0458 if (ath9k_is_chanctx_enabled()) {
0459 ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_BEACON_PREPARE);
0460 }
0461
0462 bf = ath9k_beacon_generate(sc->hw, vif);
0463
0464 if (sc->beacon.bmisscnt != 0) {
0465 ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
0466 sc->beacon.bmisscnt);
0467 sc->beacon.bmisscnt = 0;
0468 }
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 if (sc->beacon.updateslot == UPDATE) {
0487 sc->beacon.updateslot = COMMIT;
0488 sc->beacon.slotupdate = slot;
0489 } else if (sc->beacon.updateslot == COMMIT &&
0490 sc->beacon.slotupdate == slot) {
0491 ah->slottime = sc->beacon.slottime;
0492 ath9k_hw_init_global_settings(ah);
0493 sc->beacon.updateslot = OK;
0494 }
0495
0496 if (bf) {
0497 ath9k_reset_beacon_status(sc);
0498
0499 ath_dbg(common, BEACON,
0500 "Transmitting beacon for slot: %d\n", slot);
0501
0502
0503 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
0504
0505 if (!edma)
0506 ath9k_hw_txstart(ah, sc->beacon.beaconq);
0507 }
0508 }
0509
0510
0511
0512
0513 static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
0514 u32 intval)
0515 {
0516 struct ath_hw *ah = sc->sc_ah;
0517
0518 ath9k_hw_disable_interrupts(ah);
0519 ath9k_beaconq_config(sc);
0520 ath9k_hw_beaconinit(ah, nexttbtt, intval);
0521 ah->imask |= ATH9K_INT_SWBA;
0522 sc->beacon.bmisscnt = 0;
0523 ath9k_hw_set_interrupts(ah);
0524 ath9k_hw_enable_interrupts(ah);
0525 }
0526
0527 static void ath9k_beacon_stop(struct ath_softc *sc)
0528 {
0529 ath9k_hw_disable_interrupts(sc->sc_ah);
0530 sc->sc_ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
0531 sc->beacon.bmisscnt = 0;
0532 ath9k_hw_set_interrupts(sc->sc_ah);
0533 ath9k_hw_enable_interrupts(sc->sc_ah);
0534 }
0535
0536
0537
0538
0539
0540
0541 static void ath9k_beacon_config_ap(struct ath_softc *sc,
0542 struct ath_beacon_config *conf)
0543 {
0544 struct ath_hw *ah = sc->sc_ah;
0545
0546 ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF);
0547 ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
0548 }
0549
0550 static void ath9k_beacon_config_sta(struct ath_hw *ah,
0551 struct ath_beacon_config *conf)
0552 {
0553 struct ath9k_beacon_state bs;
0554
0555 if (ath9k_cmn_beacon_config_sta(ah, conf, &bs) == -EPERM)
0556 return;
0557
0558 ath9k_hw_disable_interrupts(ah);
0559 ath9k_hw_set_sta_beacon_timers(ah, &bs);
0560 ah->imask |= ATH9K_INT_BMISS;
0561
0562 ath9k_hw_set_interrupts(ah);
0563 ath9k_hw_enable_interrupts(ah);
0564 }
0565
0566 static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
0567 struct ath_beacon_config *conf)
0568 {
0569 struct ath_hw *ah = sc->sc_ah;
0570 struct ath_common *common = ath9k_hw_common(ah);
0571
0572 ath9k_reset_beacon_status(sc);
0573
0574 ath9k_cmn_beacon_config_adhoc(ah, conf);
0575
0576 ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
0577
0578
0579
0580
0581
0582 if (!conf->ibss_creator && conf->enable_beacon)
0583 set_bit(ATH_OP_BEACONS, &common->op_flags);
0584 }
0585
0586 static void ath9k_cache_beacon_config(struct ath_softc *sc,
0587 struct ath_chanctx *ctx,
0588 struct ieee80211_vif *vif)
0589 {
0590 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
0591 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0592 struct ath_beacon_config *cur_conf = &ctx->beacon;
0593
0594 ath_dbg(common, BEACON,
0595 "Caching beacon data for BSS: %pM\n", bss_conf->bssid);
0596
0597 cur_conf->beacon_interval = bss_conf->beacon_int;
0598 cur_conf->dtim_period = bss_conf->dtim_period;
0599 cur_conf->dtim_count = 1;
0600 cur_conf->ibss_creator = vif->cfg.ibss_creator;
0601
0602
0603
0604
0605
0606
0607
0608 if (cur_conf->beacon_interval == 0)
0609 cur_conf->beacon_interval = 100;
0610
0611 cur_conf->bmiss_timeout =
0612 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
0613
0614
0615
0616
0617
0618
0619 if (cur_conf->dtim_period == 0)
0620 cur_conf->dtim_period = 1;
0621
0622 ath9k_set_tsfadjust(sc, cur_conf);
0623 }
0624
0625 void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
0626 bool beacons)
0627 {
0628 struct ath_hw *ah = sc->sc_ah;
0629 struct ath_common *common = ath9k_hw_common(ah);
0630 struct ath_vif *avp;
0631 struct ath_chanctx *ctx;
0632 struct ath_beacon_config *cur_conf;
0633 unsigned long flags;
0634 bool enabled;
0635 bool skip_beacon = false;
0636
0637 if (!beacons) {
0638 clear_bit(ATH_OP_BEACONS, &common->op_flags);
0639 ath9k_beacon_stop(sc);
0640 return;
0641 }
0642
0643 if (WARN_ON(!main_vif))
0644 return;
0645
0646 avp = (void *)main_vif->drv_priv;
0647 ctx = avp->chanctx;
0648 cur_conf = &ctx->beacon;
0649 enabled = cur_conf->enable_beacon;
0650 cur_conf->enable_beacon = beacons;
0651
0652 if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
0653 ath9k_cache_beacon_config(sc, ctx, main_vif);
0654
0655 ath9k_set_beacon(sc);
0656 set_bit(ATH_OP_BEACONS, &common->op_flags);
0657 return;
0658 }
0659
0660
0661 ath9k_cache_beacon_config(sc, ctx, main_vif);
0662
0663
0664
0665
0666
0667 if (cur_conf->beacon_interval) {
0668
0669
0670
0671
0672
0673 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC &&
0674 !enabled && beacons && !main_vif->cfg.ibss_creator) {
0675 spin_lock_irqsave(&sc->sc_pm_lock, flags);
0676 sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
0677 spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
0678 skip_beacon = true;
0679 }
0680
0681
0682
0683
0684
0685 if (beacons && !skip_beacon) {
0686 set_bit(ATH_OP_BEACONS, &common->op_flags);
0687 ath9k_set_beacon(sc);
0688 } else {
0689 clear_bit(ATH_OP_BEACONS, &common->op_flags);
0690 ath9k_beacon_stop(sc);
0691 }
0692 } else {
0693 clear_bit(ATH_OP_BEACONS, &common->op_flags);
0694 ath9k_beacon_stop(sc);
0695 }
0696 }
0697
0698 void ath9k_set_beacon(struct ath_softc *sc)
0699 {
0700 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0701 struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
0702
0703 switch (sc->sc_ah->opmode) {
0704 case NL80211_IFTYPE_AP:
0705 case NL80211_IFTYPE_MESH_POINT:
0706 ath9k_beacon_config_ap(sc, cur_conf);
0707 break;
0708 case NL80211_IFTYPE_ADHOC:
0709 ath9k_beacon_config_adhoc(sc, cur_conf);
0710 break;
0711 case NL80211_IFTYPE_STATION:
0712 ath9k_beacon_config_sta(sc->sc_ah, cur_conf);
0713 break;
0714 default:
0715 ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
0716 return;
0717 }
0718 }