1f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez/* 25b68138e5659cbfd5df2879d17f9ba0b66477fecSujith Manoharan * Copyright (c) 2008-2011 Atheros Communications Inc. 3f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * 4f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * Permission to use, copy, modify, and/or distribute this software for any 5f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * purpose with or without fee is hereby granted, provided that the above 6f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * copyright notice and this permission notice appear in all copies. 7f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * 8f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 16f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 17b7f080cfe223b3b7424872639d153695615a9255Alexey Dobriyan#include <linux/dma-mapping.h> 18394cf0a1ca02e7998c8d01975b60a3cdc121e7d8Sujith#include "ath9k.h" 19f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 205379c8a26686e12058e23322615df68f9123bccdSujith#define FUDGE 2 215379c8a26686e12058e23322615df68f9123bccdSujith 22ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkaustatic void ath9k_reset_beacon_status(struct ath_softc *sc) 23ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau{ 24ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau sc->beacon.tx_processed = false; 25ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau sc->beacon.tx_last = false; 26ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau} 27ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau 28f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez/* 29f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * This function will modify certain transmit queue properties depending on 30f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * the operating mode of the station (AP or AdHoc). Parameters are AIFS 31f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * settings and channel width min/max 32f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez*/ 3394db29368a658b13a088db87c7b0bf59b1a7492dVivek Natarajanint ath_beaconq_config(struct ath_softc *sc) 34f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 35cbe61d8a41210600bc76b212edcd4dc0f55c014fSujith struct ath_hw *ah = sc->sc_ah; 36c46917bb53a546f60c7d3103407fe953c418dd5bLuis R. Rodriguez struct ath_common *common = ath9k_hw_common(ah); 3794db29368a658b13a088db87c7b0bf59b1a7492dVivek Natarajan struct ath9k_tx_queue_info qi, qi_be; 38066dae93bdfcc7af5e38a33617773fd5c6457607Felix Fietkau struct ath_txq *txq; 39f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 40b77f483fcf0579de28873828897f53371a33a0eaSujith ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); 412660b81a378ab227b78c4cc618453fa7e19a7c7bSujith if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 42f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* Always burst out beacon and CAB traffic. */ 43f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez qi.tqi_aifs = 1; 44f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez qi.tqi_cwmin = 0; 45f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez qi.tqi_cwmax = 0; 46f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } else { 47f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* Adhoc mode; important thing is to use 2x cwmin. */ 48066dae93bdfcc7af5e38a33617773fd5c6457607Felix Fietkau txq = sc->tx.txq_map[WME_AC_BE]; 49066dae93bdfcc7af5e38a33617773fd5c6457607Felix Fietkau ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); 5094db29368a658b13a088db87c7b0bf59b1a7492dVivek Natarajan qi.tqi_aifs = qi_be.tqi_aifs; 5194db29368a658b13a088db87c7b0bf59b1a7492dVivek Natarajan qi.tqi_cwmin = 4*qi_be.tqi_cwmin; 5294db29368a658b13a088db87c7b0bf59b1a7492dVivek Natarajan qi.tqi_cwmax = qi_be.tqi_cwmax; 53f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 54f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 55b77f483fcf0579de28873828897f53371a33a0eaSujith if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { 563800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, 573800276a40751539a920ef8e0537ef2e19126799Joe Perches "Unable to update h/w beacon queue parameters\n"); 58f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return 0; 59f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } else { 609fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); 61f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return 1; 62f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 63f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 64f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 65f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez/* 66f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * Associates the beacon frame buffer with a transmit descriptor. Will set 67dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau * up rate codes, and channel flags. Beacons are always sent out at the 68dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau * lowest rate, and are not retried. 69f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez*/ 70d47a61aa228709fe1704e18a2f444661c10b81c0Sujith Manoharanstatic void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, 7164b84010f9f85996a219fcc697396e7e11be3459Jouni Malinen struct ath_buf *bf, int rateidx) 72f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 73a22be22ab8fe571cce88d0d30b49f297a563c4a7Sujith struct sk_buff *skb = bf->bf_mpdu; 74cbe61d8a41210600bc76b212edcd4dc0f55c014fSujith struct ath_hw *ah = sc->sc_ah; 7543c2761364b77cd7fd20eb1f14cfee4cd1462abdLuis R. Rodriguez struct ath_common *common = ath9k_hw_common(ah); 76493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau struct ath_tx_info info; 77545750d36fa78203e28acefb4bab61ebb7c4d197Felix Fietkau struct ieee80211_supported_band *sband; 78493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau u8 chainmask = ah->txchainmask; 79545750d36fa78203e28acefb4bab61ebb7c4d197Felix Fietkau u8 rate = 0; 80f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 81ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau ath9k_reset_beacon_status(sc); 82ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau 83545750d36fa78203e28acefb4bab61ebb7c4d197Felix Fietkau sband = &sc->sbands[common->hw->conf.channel->band]; 8464b84010f9f85996a219fcc697396e7e11be3459Jouni Malinen rate = sband->bitrates[rateidx].hw_value; 85d47a61aa228709fe1704e18a2f444661c10b81c0Sujith Manoharan if (vif->bss_conf.use_short_preamble) 8664b84010f9f85996a219fcc697396e7e11be3459Jouni Malinen rate |= sband->bitrates[rateidx].hw_value_short; 879fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith 88493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau memset(&info, 0, sizeof(info)); 89493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.pkt_len = skb->len + FCS_LEN; 90493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.type = ATH9K_PKT_TYPE_BEACON; 91493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.txpower = MAX_RATE_POWER; 92493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.keyix = ATH9K_TXKEYIX_INVALID; 93493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.keytype = ATH9K_KEY_TYPE_CLEAR; 944e0ad2591adde7bec878a4b37a073427aec3e19cFelix Fietkau info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ; 95493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau 96493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.buf_addr[0] = bf->bf_buf_addr; 97493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.buf_len[0] = roundup(skb->len, 4); 98493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau 99493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.is_first = true; 100493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.is_last = true; 101493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau 102493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.qcu = sc->beacon.beaconq; 103493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau 104493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.rates[0].Tries = 1; 105493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.rates[0].Rate = rate; 106493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate); 107493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau 108493cf04fd37bf265dc3c9aad357e3e34654c86e3Felix Fietkau ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); 109f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 110f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 11128d167086227969fd6586953ee4ac682a3c394ffFelix Fietkaustatic void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) 11228d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau{ 1139ac58615d93c8a28b1c649a90a5e2ede4dfd368aFelix Fietkau struct ath_softc *sc = hw->priv; 11428d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau struct ath_common *common = ath9k_hw_common(sc->sc_ah); 11528d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau struct ath_tx_control txctl; 11628d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau 11728d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau memset(&txctl, 0, sizeof(struct ath_tx_control)); 11828d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau txctl.txq = sc->beacon.cabq; 11928d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau 120d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, XMIT, "transmitting CABQ packet, skb: %p\n", skb); 12128d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau 12228d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau if (ath_tx_start(hw, skb, &txctl) != 0) { 123d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, XMIT, "CABQ TX failed\n"); 12428d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau dev_kfree_skb_any(skb); 12528d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau } 12628d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau} 12728d167086227969fd6586953ee4ac682a3c394ffFelix Fietkau 128c52f33d05e5f8d59f02722fbc308f5f391575ca5Jouni Malinenstatic struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, 1292c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen struct ieee80211_vif *vif) 130f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 1319ac58615d93c8a28b1c649a90a5e2ede4dfd368aFelix Fietkau struct ath_softc *sc = hw->priv; 132c46917bb53a546f60c7d3103407fe953c418dd5bLuis R. Rodriguez struct ath_common *common = ath9k_hw_common(sc->sc_ah); 133f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct ath_buf *bf; 13417d7904de85125c62c7258d7cb21207f26d04048Sujith struct ath_vif *avp; 135f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct sk_buff *skb; 136f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct ath_txq *cabq; 137147583c057c43095925b5f331fe304f2d5b997baJouni Malinen struct ieee80211_tx_info *info; 138980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith int cabq_depth; 139980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 140ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau ath9k_reset_beacon_status(sc); 141ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau 1425640b08ef7e88b606c740e746cb77bc97d78508eSujith avp = (void *)vif->drv_priv; 143b77f483fcf0579de28873828897f53371a33a0eaSujith cabq = sc->beacon.cabq; 144f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 145014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active) 146f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return NULL; 147980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 1489fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith /* Release the old beacon first */ 1499fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith 150f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bf = avp->av_bcbuf; 151a22be22ab8fe571cce88d0d30b49f297a563c4a7Sujith skb = bf->bf_mpdu; 152a8fff50e4d6aad520b261b3c32e2c67a7dfb7228Jouni Malinen if (skb) { 153c1739eb3e61e160f124bc842c219011916f63068Ben Greear dma_unmap_single(sc->dev, bf->bf_buf_addr, 1549fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith skb->len, DMA_TO_DEVICE); 1553fbb9d95a96c6a03f2e484bb1665d089412640dcJouni Malinen dev_kfree_skb_any(skb); 1566cf9e995f91e5bbffb2bef85feef490e5b67605dBen Greear bf->bf_buf_addr = 0; 157a8fff50e4d6aad520b261b3c32e2c67a7dfb7228Jouni Malinen } 158f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 1599fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith /* Get a new beacon from mac80211 */ 1609fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith 161c52f33d05e5f8d59f02722fbc308f5f391575ca5Jouni Malinen skb = ieee80211_beacon_get(hw, vif); 162a8fff50e4d6aad520b261b3c32e2c67a7dfb7228Jouni Malinen bf->bf_mpdu = skb; 163a8fff50e4d6aad520b261b3c32e2c67a7dfb7228Jouni Malinen if (skb == NULL) 164a8fff50e4d6aad520b261b3c32e2c67a7dfb7228Jouni Malinen return NULL; 1654ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = 1664ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen avp->tsf_adjust; 167980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 168147583c057c43095925b5f331fe304f2d5b997baJouni Malinen info = IEEE80211_SKB_CB(skb); 169147583c057c43095925b5f331fe304f2d5b997baJouni Malinen if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 170147583c057c43095925b5f331fe304f2d5b997baJouni Malinen /* 171147583c057c43095925b5f331fe304f2d5b997baJouni Malinen * TODO: make sure the seq# gets assigned properly (vs. other 172147583c057c43095925b5f331fe304f2d5b997baJouni Malinen * TX frames) 173147583c057c43095925b5f331fe304f2d5b997baJouni Malinen */ 174980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 175b77f483fcf0579de28873828897f53371a33a0eaSujith sc->tx.seq_no += 0x10; 176147583c057c43095925b5f331fe304f2d5b997baJouni Malinen hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 177b77f483fcf0579de28873828897f53371a33a0eaSujith hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); 178147583c057c43095925b5f331fe304f2d5b997baJouni Malinen } 179980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 180c1739eb3e61e160f124bc842c219011916f63068Ben Greear bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, 181c1739eb3e61e160f124bc842c219011916f63068Ben Greear skb->len, DMA_TO_DEVICE); 1827da3c55ce849e17fd9017c7bf770a03fa083d95bGabor Juhos if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { 183f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez dev_kfree_skb_any(skb); 184f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez bf->bf_mpdu = NULL; 1856cf9e995f91e5bbffb2bef85feef490e5b67605dBen Greear bf->bf_buf_addr = 0; 1863800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "dma_mapping_error on beaconing\n"); 187f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez return NULL; 188f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez } 189f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 190c52f33d05e5f8d59f02722fbc308f5f391575ca5Jouni Malinen skb = ieee80211_get_buffered_bc(hw, vif); 191f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 192f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* 193f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * if the CABQ traffic from previous DTIM is pending and the current 194f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * beacon is also a DTIM. 19517d7904de85125c62c7258d7cb21207f26d04048Sujith * 1) if there is only one vif let the cab traffic continue. 19617d7904de85125c62c7258d7cb21207f26d04048Sujith * 2) if there are more than one vif and we are using staggered 197f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * beacons, then drain the cabq by dropping all the frames in 19817d7904de85125c62c7258d7cb21207f26d04048Sujith * the cabq so that the current vifs cab traffic can be scheduled. 199f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 200f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez spin_lock_bh(&cabq->axq_lock); 201f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez cabq_depth = cabq->axq_depth; 202f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez spin_unlock_bh(&cabq->axq_lock); 203f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 204e022edbd2bfb5f9a7ddf1cca43544f7b54c6fe02Jouni Malinen if (skb && cabq_depth) { 20517d7904de85125c62c7258d7cb21207f26d04048Sujith if (sc->nvifs > 1) { 206d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, 207226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "Flushing previous cabq traffic\n"); 2089fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith ath_draintxq(sc, cabq, false); 209f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 210f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 211f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 212d47a61aa228709fe1704e18a2f444661c10b81c0Sujith Manoharan ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx); 213f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 214e022edbd2bfb5f9a7ddf1cca43544f7b54c6fe02Jouni Malinen while (skb) { 215c52f33d05e5f8d59f02722fbc308f5f391575ca5Jouni Malinen ath_tx_cabq(hw, skb); 216c52f33d05e5f8d59f02722fbc308f5f391575ca5Jouni Malinen skb = ieee80211_get_buffered_bc(hw, vif); 217e022edbd2bfb5f9a7ddf1cca43544f7b54c6fe02Jouni Malinen } 218f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 219f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return bf; 220f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 221f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 2229ac58615d93c8a28b1c649a90a5e2ede4dfd368aFelix Fietkauint ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) 223f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 224c46917bb53a546f60c7d3103407fe953c418dd5bLuis R. Rodriguez struct ath_common *common = ath9k_hw_common(sc->sc_ah); 22517d7904de85125c62c7258d7cb21207f26d04048Sujith struct ath_vif *avp; 226f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct ath_buf *bf; 227f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct sk_buff *skb; 2289814f6b34be5179849c0872e81eb99286ef4b051Steve Brown struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 229459f5f90f1bd959ced04761406415b178b315177Sujith __le64 tstamp; 230f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 2315640b08ef7e88b606c740e746cb77bc97d78508eSujith avp = (void *)vif->drv_priv; 232f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 233f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* Allocate a beacon descriptor if we haven't done so. */ 234f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (!avp->av_bcbuf) { 235980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith /* Allocate beacon state for hostap/ibss. We know 236980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith * a buffer is available. */ 237b77f483fcf0579de28873828897f53371a33a0eaSujith avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, 238980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith struct ath_buf, list); 239f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez list_del(&avp->av_bcbuf->list); 240f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 2414801416c76a3a355076d6d371c00270dfe332e1cBen Greear if (ath9k_uses_beacons(vif->type)) { 242f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez int slot; 243f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* 24417d7904de85125c62c7258d7cb21207f26d04048Sujith * Assign the vif to a beacon xmit slot. As 245f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * above, this cannot fail to find one. 246f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 247f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez avp->av_bslot = 0; 248f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez for (slot = 0; slot < ATH_BCBUF; slot++) 2492c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen if (sc->beacon.bslot[slot] == NULL) { 250f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez avp->av_bslot = slot; 251014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan avp->is_bslot_active = false; 252774610e4f26cb3d9da14a8b5974324c9e51017bdFelix Fietkau 253f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* NB: keep looking for a double slot */ 254774610e4f26cb3d9da14a8b5974324c9e51017bdFelix Fietkau if (slot == 0 || !sc->beacon.bslot[slot-1]) 255774610e4f26cb3d9da14a8b5974324c9e51017bdFelix Fietkau break; 256f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 2572c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); 2582c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen sc->beacon.bslot[avp->av_bslot] = vif; 25917d7904de85125c62c7258d7cb21207f26d04048Sujith sc->nbcnvifs++; 260f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 261f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 262f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 2639fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith /* release the previous beacon frame, if it already exists. */ 264f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bf = avp->av_bcbuf; 265f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (bf->bf_mpdu != NULL) { 266a22be22ab8fe571cce88d0d30b49f297a563c4a7Sujith skb = bf->bf_mpdu; 267c1739eb3e61e160f124bc842c219011916f63068Ben Greear dma_unmap_single(sc->dev, bf->bf_buf_addr, 2689fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith skb->len, DMA_TO_DEVICE); 269f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez dev_kfree_skb_any(skb); 270f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bf->bf_mpdu = NULL; 2716cf9e995f91e5bbffb2bef85feef490e5b67605dBen Greear bf->bf_buf_addr = 0; 272f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 273f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 2749fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith /* NB: the beacon data buffer must be 32-bit aligned. */ 2755640b08ef7e88b606c740e746cb77bc97d78508eSujith skb = ieee80211_beacon_get(sc->hw, vif); 276d7e86c3219a1287dd1350a590ee79c8753ff2420Felix Fietkau if (skb == NULL) 277f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return -ENOMEM; 278f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 279459f5f90f1bd959ced04761406415b178b315177Sujith tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; 280dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); 2814ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen /* Calculate a TSF adjustment factor required for staggered beacons. */ 282f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (avp->av_bslot > 0) { 283f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez u64 tsfadjust; 284f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez int intval; 285f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 2869814f6b34be5179849c0872e81eb99286ef4b051Steve Brown intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; 287f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 288f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* 2894ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen * Calculate the TSF offset for this beacon slot, i.e., the 2904ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen * number of usecs that need to be added to the timestamp field 2914ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen * in Beacon and Probe Response frames. Beacon slot 0 is 2924ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen * processed at the correct offset, so it does not require TSF 2934ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen * adjustment. Other slots are adjusted to get the timestamp 2944ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen * close to the TBTT for the BSS. 295f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 296dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; 297dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau avp->tsf_adjust = cpu_to_le64(tsfadjust); 298f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 299d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, 300226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "stagger beacons, bslot %d intval %u tsfadjust %llu\n", 301226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches avp->av_bslot, intval, (unsigned long long)tsfadjust); 302f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 3034ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = 3044ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen avp->tsf_adjust; 3054ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen } else 3064ed96f04f8a1869757f4dd4a9283a18ec63c442fJouni Malinen avp->tsf_adjust = cpu_to_le64(0); 307f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 308f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez bf->bf_mpdu = skb; 309c1739eb3e61e160f124bc842c219011916f63068Ben Greear bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, 310c1739eb3e61e160f124bc842c219011916f63068Ben Greear skb->len, DMA_TO_DEVICE); 3117da3c55ce849e17fd9017c7bf770a03fa083d95bGabor Juhos if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { 312f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez dev_kfree_skb_any(skb); 313f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez bf->bf_mpdu = NULL; 3146cf9e995f91e5bbffb2bef85feef490e5b67605dBen Greear bf->bf_buf_addr = 0; 3153800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "dma_mapping_error on beacon alloc\n"); 316f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez return -ENOMEM; 317f8316df10c4e3bec5b4c3a5a8e026c577640c3a6Luis R. Rodriguez } 318014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan avp->is_bslot_active = true; 319f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 320f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return 0; 321f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 322f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 32317d7904de85125c62c7258d7cb21207f26d04048Sujithvoid ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) 324f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 325f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (avp->av_bcbuf != NULL) { 326f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct ath_buf *bf; 327f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 328f60c49b67dd6db2ccb740a6a671414f9dab00c4fRajkumar Manoharan avp->is_bslot_active = false; 329f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (avp->av_bslot != -1) { 3302c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen sc->beacon.bslot[avp->av_bslot] = NULL; 33117d7904de85125c62c7258d7cb21207f26d04048Sujith sc->nbcnvifs--; 33266da424177db4f4f2fa7a462db5912655aad966fRajkumar Manoharan avp->av_bslot = -1; 333f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 334f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 335f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bf = avp->av_bcbuf; 336f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (bf->bf_mpdu != NULL) { 337a22be22ab8fe571cce88d0d30b49f297a563c4a7Sujith struct sk_buff *skb = bf->bf_mpdu; 338c1739eb3e61e160f124bc842c219011916f63068Ben Greear dma_unmap_single(sc->dev, bf->bf_buf_addr, 3399fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith skb->len, DMA_TO_DEVICE); 340f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez dev_kfree_skb_any(skb); 341f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bf->bf_mpdu = NULL; 3426cf9e995f91e5bbffb2bef85feef490e5b67605dBen Greear bf->bf_buf_addr = 0; 343f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 344b77f483fcf0579de28873828897f53371a33a0eaSujith list_add_tail(&bf->list, &sc->beacon.bbuf); 345f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 346f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez avp->av_bcbuf = NULL; 347f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 348f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 349f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 3509fc9ab0a6929c9f137747df0ecf294e9582607f9Sujithvoid ath_beacon_tasklet(unsigned long data) 351f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 352f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct ath_softc *sc = (struct ath_softc *)data; 3539814f6b34be5179849c0872e81eb99286ef4b051Steve Brown struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 354cbe61d8a41210600bc76b212edcd4dc0f55c014fSujith struct ath_hw *ah = sc->sc_ah; 355c46917bb53a546f60c7d3103407fe953c418dd5bLuis R. Rodriguez struct ath_common *common = ath9k_hw_common(ah); 356f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez struct ath_buf *bf = NULL; 3572c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen struct ieee80211_vif *vif; 35898f0a5eb02bbfff662664bf65f469dc4abd701fdMohammed Shafi Shajakhan bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); 3592c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen int slot; 360c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau u32 bfaddr, bc = 0; 361f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 362f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* 363f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * Check if the previous beacon has gone out. If 364f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * not don't try to post another, skip this period 365f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * and wait for the next. Missed beacons indicate 366f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * a problem and should not occur. If we miss too 367f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * many consecutive beacons reset the device. 368f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 369b77f483fcf0579de28873828897f53371a33a0eaSujith if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { 370b77f483fcf0579de28873828897f53371a33a0eaSujith sc->beacon.bmisscnt++; 3719546aae0863c12a3d00b1ed5cbd316520733200bSujith 372c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { 373d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BSTUCK, 374226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "missed %u consecutive beacons\n", 375226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches sc->beacon.bmisscnt); 376efff395e97fffd55c60c77c09a18deba8d84e2c0Felix Fietkau ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); 37787c510fe2d4f193cd4eb518364a2dfa5059b1218Felix Fietkau if (sc->beacon.bmisscnt > 3) 37887c510fe2d4f193cd4eb518364a2dfa5059b1218Felix Fietkau ath9k_hw_bstuck_nfcal(ah); 379b77f483fcf0579de28873828897f53371a33a0eaSujith } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { 380d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); 381b74444f8a9039603715973a56df588a5d800c4efJeff Hansen sc->sc_flags |= SC_OP_TSF_RESET; 382236de5149b9cbec3e76aef00a4663a8de7feeebeFelix Fietkau ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 383f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 3849546aae0863c12a3d00b1ed5cbd316520733200bSujith 385f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez return; 386f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 387980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 388f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* 389f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * Generate beacon frames. we are sending frames 390f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * staggered so calculate the slot for this frame based 391f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * on the tsf to safeguard against missing an swba. 392f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 393f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 394f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 395c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau if (ah->opmode == NL80211_IFTYPE_AP) { 396c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau u16 intval; 397c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau u32 tsftu; 398c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau u64 tsf; 399c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau 400c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; 401c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau tsf = ath9k_hw_gettsf64(ah); 402c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); 403c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); 404c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau slot = (tsftu % (intval * ATH_BCBUF)) / intval; 405c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau vif = sc->beacon.bslot[slot]; 406c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau 407d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, 408c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", 409c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau slot, tsf, tsftu / ATH_BCBUF, intval, vif); 410c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau } else { 411c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau slot = 0; 412c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau vif = sc->beacon.bslot[slot]; 413c6820f1e6c8273ca4b8f94c2354193d19e1a5c47Felix Fietkau } 414980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 415980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 416f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bfaddr = 0; 4172c3db3d51ee1fcf84f5828788905a4c091b9ae27Jouni Malinen if (vif) { 4187545daf498c43e548506212310e6c75382d2731dFelix Fietkau bf = ath_beacon_generate(sc->hw, vif); 419f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (bf != NULL) { 420f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bfaddr = bf->bf_daddr; 421f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez bc = 1; 422f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 423c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau 424c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau if (sc->beacon.bmisscnt != 0) { 425d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BSTUCK, 426c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau "resume beacon xmit after %u misses\n", 427c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau sc->beacon.bmisscnt); 428c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau sc->beacon.bmisscnt = 0; 429c944daf46a8cfa50d6c1f54d4842180d0384c594Felix Fietkau } 430f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 4319546aae0863c12a3d00b1ed5cbd316520733200bSujith 432f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* 433f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * Handle slot time change when a non-ERP station joins/leaves 434f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * an 11g network. The 802.11 layer notifies us via callback, 435f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * we mark updateslot, then wait one beacon before effecting 436f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * the change. This gives associated stations at least one 437f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * beacon interval to note the state change. 438f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * 439f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * NB: The slot time change state machine is clocked according 440f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * to whether we are bursting or staggering beacons. We 441f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * recognize the request to update and record the current 442f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * slot then don't transition until that slot is reached 443f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * again. If we miss a beacon for that slot then we'll be 444f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * slow to transition but we'll be sure at least one beacon 445f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * interval has passed. When bursting slot is always left 446f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez * set to ATH_BCBUF so this check is a noop. 447f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 448b77f483fcf0579de28873828897f53371a33a0eaSujith if (sc->beacon.updateslot == UPDATE) { 449b77f483fcf0579de28873828897f53371a33a0eaSujith sc->beacon.updateslot = COMMIT; /* commit next beacon */ 450b77f483fcf0579de28873828897f53371a33a0eaSujith sc->beacon.slotupdate = slot; 451b77f483fcf0579de28873828897f53371a33a0eaSujith } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { 4520005baf4a31efe6de6f922f73ccbd3762a110062Felix Fietkau ah->slottime = sc->beacon.slottime; 4530005baf4a31efe6de6f922f73ccbd3762a110062Felix Fietkau ath9k_hw_init_global_settings(ah); 454b77f483fcf0579de28873828897f53371a33a0eaSujith sc->beacon.updateslot = OK; 455ff37e337beb838d4c2540fa93b2c4c632ee17750Sujith } 456f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez if (bfaddr != 0) { 457f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez /* NB: cabq traffic should already be queued and primed */ 458b77f483fcf0579de28873828897f53371a33a0eaSujith ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); 45998f0a5eb02bbfff662664bf65f469dc4abd701fdMohammed Shafi Shajakhan 46098f0a5eb02bbfff662664bf65f469dc4abd701fdMohammed Shafi Shajakhan if (!edma) 46198f0a5eb02bbfff662664bf65f469dc4abd701fdMohammed Shafi Shajakhan ath9k_hw_txstart(ah, sc->beacon.beaconq); 462f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 46317d7904de85125c62c7258d7cb21207f26d04048Sujith sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ 464f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 465f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 466f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 46721526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguezstatic void ath9k_beacon_init(struct ath_softc *sc, 46821526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez u32 next_beacon, 46921526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez u32 beacon_period) 47021526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez{ 471dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau if (sc->sc_flags & SC_OP_TSF_RESET) { 47221526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez ath9k_ps_wakeup(sc); 473dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau ath9k_hw_reset_tsf(sc->sc_ah); 474dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau } 47521526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez 47621526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); 47721526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez 478dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau if (sc->sc_flags & SC_OP_TSF_RESET) { 47921526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez ath9k_ps_restore(sc); 480dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau sc->sc_flags &= ~SC_OP_TSF_RESET; 481dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau } 48221526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez} 48321526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez 484f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez/* 4855379c8a26686e12058e23322615df68f9123bccdSujith * For multi-bss ap support beacons are either staggered evenly over N slots or 4865379c8a26686e12058e23322615df68f9123bccdSujith * burst together. For the former arrange for the SWBA to be delivered for each 4875379c8a26686e12058e23322615df68f9123bccdSujith * slot. Slots that are not occupied will generate nothing. 488f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez */ 4895379c8a26686e12058e23322615df68f9123bccdSujithstatic void ath_beacon_config_ap(struct ath_softc *sc, 490d31e20af9f65e38429a3ed32175f8e233bdcd2b2Vasanthakumar Thiagarajan struct ath_beacon_config *conf) 491f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 4923069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin struct ath_hw *ah = sc->sc_ah; 493980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith u32 nexttbtt, intval; 494f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 4955379c8a26686e12058e23322615df68f9123bccdSujith /* NB: the beacon interval is kept internally in TU's */ 496f29f5c0882bdd58c42b8176ee0b578f92589fda2Rajkumar Manoharan intval = TU_TO_USEC(conf->beacon_interval); 4975379c8a26686e12058e23322615df68f9123bccdSujith intval /= ATH_BCBUF; /* for staggered beacons */ 4985379c8a26686e12058e23322615df68f9123bccdSujith nexttbtt = intval; 499d8728ee919282c7b01b65cd479ec1e2a9c5d3ba8Felix Fietkau 5005379c8a26686e12058e23322615df68f9123bccdSujith /* 5015379c8a26686e12058e23322615df68f9123bccdSujith * In AP mode we enable the beacon timers and SWBA interrupts to 5025379c8a26686e12058e23322615df68f9123bccdSujith * prepare beacon frames. 5035379c8a26686e12058e23322615df68f9123bccdSujith */ 5043069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin ah->imask |= ATH9K_INT_SWBA; 5055379c8a26686e12058e23322615df68f9123bccdSujith ath_beaconq_config(sc); 506f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 5075379c8a26686e12058e23322615df68f9123bccdSujith /* Set the computed AP beacon timers */ 508f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 5094df3071ebd92ef7115b409da64d0eb405d24a631Felix Fietkau ath9k_hw_disable_interrupts(ah); 510c31c8261bf7b817e323d29ba66c031f6b0982680Felix Fietkau sc->sc_flags |= SC_OP_TSF_RESET; 51121526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez ath9k_beacon_init(sc, nexttbtt, intval); 5125379c8a26686e12058e23322615df68f9123bccdSujith sc->beacon.bmisscnt = 0; 51372d874c67c3cdf21ca95045baabac6a5843222d8Felix Fietkau ath9k_hw_set_interrupts(ah); 514b037b693265e5c83ddc3f003a713d19b9832bf24Rajkumar Manoharan ath9k_hw_enable_interrupts(ah); 5155379c8a26686e12058e23322615df68f9123bccdSujith} 516459f5f90f1bd959ced04761406415b178b315177Sujith 5175379c8a26686e12058e23322615df68f9123bccdSujith/* 5185379c8a26686e12058e23322615df68f9123bccdSujith * This sets up the beacon timers according to the timestamp of the last 5195379c8a26686e12058e23322615df68f9123bccdSujith * received beacon and the current TSF, configures PCF and DTIM 5205379c8a26686e12058e23322615df68f9123bccdSujith * handling, programs the sleep registers so the hardware will wakeup in 5215379c8a26686e12058e23322615df68f9123bccdSujith * time to receive beacons, and configures the beacon miss handling so 5225379c8a26686e12058e23322615df68f9123bccdSujith * we'll receive a BMISS interrupt when we stop seeing beacons from the AP 5235379c8a26686e12058e23322615df68f9123bccdSujith * we've associated with. 5245379c8a26686e12058e23322615df68f9123bccdSujith */ 5255379c8a26686e12058e23322615df68f9123bccdSujithstatic void ath_beacon_config_sta(struct ath_softc *sc, 526d31e20af9f65e38429a3ed32175f8e233bdcd2b2Vasanthakumar Thiagarajan struct ath_beacon_config *conf) 5275379c8a26686e12058e23322615df68f9123bccdSujith{ 5283069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin struct ath_hw *ah = sc->sc_ah; 5293069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin struct ath_common *common = ath9k_hw_common(ah); 5305379c8a26686e12058e23322615df68f9123bccdSujith struct ath9k_beacon_state bs; 5315379c8a26686e12058e23322615df68f9123bccdSujith int dtimperiod, dtimcount, sleepduration; 5325379c8a26686e12058e23322615df68f9123bccdSujith int cfpperiod, cfpcount; 5335379c8a26686e12058e23322615df68f9123bccdSujith u32 nexttbtt = 0, intval, tsftu; 5345379c8a26686e12058e23322615df68f9123bccdSujith u64 tsf; 535267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen int num_beacons, offset, dtim_dec_count, cfp_dec_count; 5365379c8a26686e12058e23322615df68f9123bccdSujith 5371a20034a73a40b8056731f9db0c535cec2961eb7Senthil Balasubramanian /* No need to configure beacon if we are not associated */ 5381a20034a73a40b8056731f9db0c535cec2961eb7Senthil Balasubramanian if (!common->curaid) { 539d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, 540226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "STA is not yet associated..skipping beacon config\n"); 5411a20034a73a40b8056731f9db0c535cec2961eb7Senthil Balasubramanian return; 5421a20034a73a40b8056731f9db0c535cec2961eb7Senthil Balasubramanian } 5431a20034a73a40b8056731f9db0c535cec2961eb7Senthil Balasubramanian 5445379c8a26686e12058e23322615df68f9123bccdSujith memset(&bs, 0, sizeof(bs)); 545f29f5c0882bdd58c42b8176ee0b578f92589fda2Rajkumar Manoharan intval = conf->beacon_interval; 5465379c8a26686e12058e23322615df68f9123bccdSujith 5475379c8a26686e12058e23322615df68f9123bccdSujith /* 5485379c8a26686e12058e23322615df68f9123bccdSujith * Setup dtim and cfp parameters according to 5495379c8a26686e12058e23322615df68f9123bccdSujith * last beacon we received (which may be none). 5505379c8a26686e12058e23322615df68f9123bccdSujith */ 5515379c8a26686e12058e23322615df68f9123bccdSujith dtimperiod = conf->dtim_period; 5525379c8a26686e12058e23322615df68f9123bccdSujith dtimcount = conf->dtim_count; 5535379c8a26686e12058e23322615df68f9123bccdSujith if (dtimcount >= dtimperiod) /* NB: sanity check */ 5545379c8a26686e12058e23322615df68f9123bccdSujith dtimcount = 0; 5555379c8a26686e12058e23322615df68f9123bccdSujith cfpperiod = 1; /* NB: no PCF support yet */ 5565379c8a26686e12058e23322615df68f9123bccdSujith cfpcount = 0; 5575379c8a26686e12058e23322615df68f9123bccdSujith 5585379c8a26686e12058e23322615df68f9123bccdSujith sleepduration = conf->listen_interval * intval; 5595379c8a26686e12058e23322615df68f9123bccdSujith 5605379c8a26686e12058e23322615df68f9123bccdSujith /* 5615379c8a26686e12058e23322615df68f9123bccdSujith * Pull nexttbtt forward to reflect the current 5625379c8a26686e12058e23322615df68f9123bccdSujith * TSF and calculate dtim+cfp state for the result. 5635379c8a26686e12058e23322615df68f9123bccdSujith */ 5643069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin tsf = ath9k_hw_gettsf64(ah); 5655379c8a26686e12058e23322615df68f9123bccdSujith tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 566267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen 567267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen num_beacons = tsftu / intval + 1; 568267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen offset = tsftu % intval; 569267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen nexttbtt = tsftu - offset; 570267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen if (offset) 5715379c8a26686e12058e23322615df68f9123bccdSujith nexttbtt += intval; 572267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen 573267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen /* DTIM Beacon every dtimperiod Beacon */ 574267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen dtim_dec_count = num_beacons % dtimperiod; 575267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen /* CFP every cfpperiod DTIM Beacon */ 576267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; 577267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen if (dtim_dec_count) 578267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen cfp_dec_count++; 579267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen 580267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen dtimcount -= dtim_dec_count; 581267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen if (dtimcount < 0) 582267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen dtimcount += dtimperiod; 583267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen 584267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen cfpcount -= cfp_dec_count; 585267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen if (cfpcount < 0) 586267a90127472be70b02ab13cbd355b5013e2aa51Jouni Malinen cfpcount += cfpperiod; 5875379c8a26686e12058e23322615df68f9123bccdSujith 5885379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_intval = intval; 5895379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_nexttbtt = nexttbtt; 5905379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_dtimperiod = dtimperiod*intval; 5915379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; 5925379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; 5935379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; 5945379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_cfpmaxduration = 0; 5955379c8a26686e12058e23322615df68f9123bccdSujith 5965379c8a26686e12058e23322615df68f9123bccdSujith /* 5975379c8a26686e12058e23322615df68f9123bccdSujith * Calculate the number of consecutive beacons to miss* before taking 5985379c8a26686e12058e23322615df68f9123bccdSujith * a BMISS interrupt. The configuration is specified in TU so we only 5995379c8a26686e12058e23322615df68f9123bccdSujith * need calculate based on the beacon interval. Note that we clamp the 6005379c8a26686e12058e23322615df68f9123bccdSujith * result to at most 15 beacons. 6015379c8a26686e12058e23322615df68f9123bccdSujith */ 6025379c8a26686e12058e23322615df68f9123bccdSujith if (sleepduration > intval) { 6035379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_bmissthreshold = conf->listen_interval * 6045379c8a26686e12058e23322615df68f9123bccdSujith ATH_DEFAULT_BMISS_LIMIT / 2; 605f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } else { 6065379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval); 6075379c8a26686e12058e23322615df68f9123bccdSujith if (bs.bs_bmissthreshold > 15) 6085379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_bmissthreshold = 15; 6095379c8a26686e12058e23322615df68f9123bccdSujith else if (bs.bs_bmissthreshold <= 0) 6105379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_bmissthreshold = 1; 611f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez } 612f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 6135379c8a26686e12058e23322615df68f9123bccdSujith /* 6145379c8a26686e12058e23322615df68f9123bccdSujith * Calculate sleep duration. The configuration is given in ms. 6155379c8a26686e12058e23322615df68f9123bccdSujith * We ensure a multiple of the beacon period is used. Also, if the sleep 6165379c8a26686e12058e23322615df68f9123bccdSujith * duration is greater than the DTIM period then it makes senses 6175379c8a26686e12058e23322615df68f9123bccdSujith * to make it a multiple of that. 6185379c8a26686e12058e23322615df68f9123bccdSujith * 6195379c8a26686e12058e23322615df68f9123bccdSujith * XXX fixed at 100ms 6205379c8a26686e12058e23322615df68f9123bccdSujith */ 621980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 6225379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); 6235379c8a26686e12058e23322615df68f9123bccdSujith if (bs.bs_sleepduration > bs.bs_dtimperiod) 6245379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_sleepduration = bs.bs_dtimperiod; 625980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 6265379c8a26686e12058e23322615df68f9123bccdSujith /* TSF out of range threshold fixed at 1 second */ 6275379c8a26686e12058e23322615df68f9123bccdSujith bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; 628f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 629d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); 630d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, 631226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", 632226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches bs.bs_bmissthreshold, bs.bs_sleepduration, 633226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); 634f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 6355379c8a26686e12058e23322615df68f9123bccdSujith /* Set the computed STA beacon timers */ 636980b24da6f1725c2d0b32c9484d06cd7d09d3c4bSujith 6374df3071ebd92ef7115b409da64d0eb405d24a631Felix Fietkau ath9k_hw_disable_interrupts(ah); 6383069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin ath9k_hw_set_sta_beacon_timers(ah, &bs); 6393069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin ah->imask |= ATH9K_INT_BMISS; 640deb751880af6f2dce6cdc232a7b023f2b58cd815Rajkumar Manoharan 64172d874c67c3cdf21ca95045baabac6a5843222d8Felix Fietkau ath9k_hw_set_interrupts(ah); 642e8fe7336849e469978c9bbcc435903595912c4d3Rajkumar Manoharan ath9k_hw_enable_interrupts(ah); 6435379c8a26686e12058e23322615df68f9123bccdSujith} 644f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 6455379c8a26686e12058e23322615df68f9123bccdSujithstatic void ath_beacon_config_adhoc(struct ath_softc *sc, 646ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan struct ath_beacon_config *conf) 6475379c8a26686e12058e23322615df68f9123bccdSujith{ 6483069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin struct ath_hw *ah = sc->sc_ah; 6493069168c82d65f88e4ac76eda09baff02adfd743Pavel Roskin struct ath_common *common = ath9k_hw_common(ah); 65081168e509f06aa205b240c1804ec2b9b5add4772Fabrice Deyber u32 tsf, intval, nexttbtt; 651dd347f2fb2ddb20a80e9a8285252bf208ab91398Felix Fietkau 652ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau ath9k_reset_beacon_status(sc); 653ba4903f97a275ed0967b58ff882f8ab41bec24adFelix Fietkau 654f29f5c0882bdd58c42b8176ee0b578f92589fda2Rajkumar Manoharan intval = TU_TO_USEC(conf->beacon_interval); 65581168e509f06aa205b240c1804ec2b9b5add4772Fabrice Deyber tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval); 65681168e509f06aa205b240c1804ec2b9b5add4772Fabrice Deyber nexttbtt = tsf + intval; 657f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 658d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, BEACON, "IBSS nexttbtt %u intval %u (%u)\n", 659226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches nexttbtt, intval, conf->beacon_interval); 6609fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith 6615379c8a26686e12058e23322615df68f9123bccdSujith /* 6625379c8a26686e12058e23322615df68f9123bccdSujith * In IBSS mode enable the beacon timers but only enable SWBA interrupts 6635379c8a26686e12058e23322615df68f9123bccdSujith * if we need to manually prepare beacon frames. Otherwise we use a 6645379c8a26686e12058e23322615df68f9123bccdSujith * self-linked tx descriptor and let the hardware deal with things. 6655379c8a26686e12058e23322615df68f9123bccdSujith */ 666a65e4cb402b5f3e120570ba1faca4354d47e8f2fFelix Fietkau ah->imask |= ATH9K_INT_SWBA; 6679fc9ab0a6929c9f137747df0ecf294e9582607f9Sujith 6685379c8a26686e12058e23322615df68f9123bccdSujith ath_beaconq_config(sc); 6695379c8a26686e12058e23322615df68f9123bccdSujith 6705379c8a26686e12058e23322615df68f9123bccdSujith /* Set the computed ADHOC beacon timers */ 6715379c8a26686e12058e23322615df68f9123bccdSujith 6724df3071ebd92ef7115b409da64d0eb405d24a631Felix Fietkau ath9k_hw_disable_interrupts(ah); 67321526d57ad98635fe12dc8efe46a3d992439a443Luis R. Rodriguez ath9k_beacon_init(sc, nexttbtt, intval); 6745379c8a26686e12058e23322615df68f9123bccdSujith sc->beacon.bmisscnt = 0; 675e8fe7336849e469978c9bbcc435903595912c4d3Rajkumar Manoharan 67672d874c67c3cdf21ca95045baabac6a5843222d8Felix Fietkau ath9k_hw_set_interrupts(ah); 677e8fe7336849e469978c9bbcc435903595912c4d3Rajkumar Manoharan ath9k_hw_enable_interrupts(ah); 678f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 679f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez 68099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharanstatic bool ath9k_allow_beacon_config(struct ath_softc *sc, 68199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ieee80211_vif *vif) 682f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez{ 6836b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 684c46917bb53a546f60c7d3103407fe953c418dd5bLuis R. Rodriguez struct ath_common *common = ath9k_hw_common(sc->sc_ah); 68599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 68699e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ath_vif *avp = (void *)vif->drv_priv; 6875379c8a26686e12058e23322615df68f9123bccdSujith 68899e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan /* 68999e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan * Can not have different beacon interval on multiple 69099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan * AP interface case 69199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan */ 69299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && 69399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan (sc->nbcnvifs > 1) && 69499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan (vif->type == NL80211_IFTYPE_AP) && 69599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan (cur_conf->beacon_interval != bss_conf->beacon_int)) { 696d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, CONFIG, 697d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches "Changing beacon interval of multiple AP interfaces !\n"); 69899e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan return false; 69999e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan } 70099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan /* 70199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan * Can not configure station vif's beacon config 70299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan * while on AP opmode 70399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan */ 70499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && 70599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan (vif->type != NL80211_IFTYPE_AP)) { 706d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, CONFIG, 70799e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan "STA vif's beacon not allowed on AP mode\n"); 70899e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan return false; 70999e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan } 71099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan /* 71199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan * Do not allow beacon config if HW was already configured 71299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan * with another STA vif 71399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan */ 71499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && 71599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan (vif->type == NL80211_IFTYPE_STATION) && 71699e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan (sc->sc_flags & SC_OP_BEACONS) && 71799e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan !avp->primary_sta_vif) { 718d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, CONFIG, 71999e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan "Beacon already configured for a station interface\n"); 72099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan return false; 721ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan } 72299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan return true; 72399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan} 72499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan 72599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharanvoid ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) 72699e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan{ 72799e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 72899e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 729ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan 73099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan if (!ath9k_allow_beacon_config(sc, vif)) 73199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan return; 73299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan 73399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan /* Setup the beacon configuration parameters */ 73499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan cur_conf->beacon_interval = bss_conf->beacon_int; 73599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan cur_conf->dtim_period = bss_conf->dtim_period; 7364801416c76a3a355076d6d371c00270dfe332e1cBen Greear cur_conf->listen_interval = 1; 7374801416c76a3a355076d6d371c00270dfe332e1cBen Greear cur_conf->dtim_count = 1; 7384801416c76a3a355076d6d371c00270dfe332e1cBen Greear cur_conf->bmiss_timeout = 7394801416c76a3a355076d6d371c00270dfe332e1cBen Greear ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 7406b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan 741c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan /* 742c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan * It looks like mac80211 may end up using beacon interval of zero in 743c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan * some cases (at least for mesh point). Avoid getting into an 744c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan * infinite loop by using a bit safer value instead. To be safe, 745c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan * do sanity check on beacon interval for all operating modes. 746c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan */ 747c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan if (cur_conf->beacon_interval == 0) 748c4f9f16b309b65f9f578ec4ba78b3efa106cf65dVasanthakumar Thiagarajan cur_conf->beacon_interval = 100; 7496b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan 750ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan /* 7513a2329f2680796b0c09ff207803ea880a481c3a4Mohammed Shafi Shajakhan * We don't parse dtim period from mac80211 during the driver 7523a2329f2680796b0c09ff207803ea880a481c3a4Mohammed Shafi Shajakhan * initialization as it breaks association with hidden-ssid 7533a2329f2680796b0c09ff207803ea880a481c3a4Mohammed Shafi Shajakhan * AP and it causes latency in roaming 754ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan */ 755ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan if (cur_conf->dtim_period == 0) 756ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan cur_conf->dtim_period = 1; 757ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan 75899e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan ath_set_beacon(sc); 75999e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan} 76099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan 7618e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharanstatic bool ath_has_valid_bslot(struct ath_softc *sc) 7628e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan{ 7638e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan struct ath_vif *avp; 7648e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan int slot; 7658e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan bool found = false; 7668e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan 7678e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan for (slot = 0; slot < ATH_BCBUF; slot++) { 7688e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan if (sc->beacon.bslot[slot]) { 7698e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan avp = (void *)sc->beacon.bslot[slot]->drv_priv; 7708e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan if (avp->is_bslot_active) { 7718e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan found = true; 7728e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan break; 7738e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan } 7748e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan } 7758e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan } 7768e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan return found; 7778e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan} 7788e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan 7798e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan 78099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharanvoid ath_set_beacon(struct ath_softc *sc) 78199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan{ 78299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ath_common *common = ath9k_hw_common(sc->sc_ah); 78399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 78499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan 78526cd322bacd3d65fffef6f8418c2fdad5b42e4b5Felix Fietkau switch (sc->sc_ah->opmode) { 7866b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan case NL80211_IFTYPE_AP: 7878e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan if (ath_has_valid_bslot(sc)) 7888e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan ath_beacon_config_ap(sc, cur_conf); 7896b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan break; 7906b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan case NL80211_IFTYPE_ADHOC: 7916b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan case NL80211_IFTYPE_MESH_POINT: 792ee832d3e9e72abf83931205a2f5379944be501c2Mohammed Shafi Shajakhan ath_beacon_config_adhoc(sc, cur_conf); 7936b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan break; 7946b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan case NL80211_IFTYPE_STATION: 7956b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan ath_beacon_config_sta(sc, cur_conf); 7966b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan break; 7976b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan default: 798d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); 7996b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan return; 8006b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan } 8016b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan 8026b96f93e962e25d38d7a73c0009597672d87c496Vasanthakumar Thiagarajan sc->sc_flags |= SC_OP_BEACONS; 803f078f209704849c86bd43c0beccfc1f410ed1c66Luis R. Rodriguez} 804014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan 805014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharanvoid ath9k_set_beaconing_status(struct ath_softc *sc, bool status) 806014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan{ 807014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan struct ath_hw *ah = sc->sc_ah; 808014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan 8098e22ad323fb5b7cefb572bd8730e3abef95cdf90Rajkumar Manoharan if (!ath_has_valid_bslot(sc)) 81099e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan return; 81199e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan 81299e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan ath9k_ps_wakeup(sc); 81399e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan if (status) { 81499e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan /* Re-enable beaconing */ 81599e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4Rajkumar Manoharan ah->imask |= ATH9K_INT_SWBA; 81672d874c67c3cdf21ca95045baabac6a5843222d8Felix Fietkau ath9k_hw_set_interrupts(ah); 817014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan } else { 818014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan /* Disable SWBA interrupt */ 819014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan ah->imask &= ~ATH9K_INT_SWBA; 82072d874c67c3cdf21ca95045baabac6a5843222d8Felix Fietkau ath9k_hw_set_interrupts(ah); 821014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan tasklet_kill(&sc->bcon_tasklet); 822efff395e97fffd55c60c77c09a18deba8d84e2c0Felix Fietkau ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); 823014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan } 824014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan ath9k_ps_restore(sc); 825014cf3bb1e19a61c53666d7f990f584f1b7af364Rajkumar Manoharan} 826