aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/beacon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c445
1 files changed, 275 insertions, 170 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 4d4b22d52dfd..d4d8ceced89b 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc. 2 * Copyright (c) 2008-2011 Atheros Communications Inc.
3 * 3 *
4 * Permission to use, copy, modify, and/or distribute this software for any 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 5 * purpose with or without fee is hereby granted, provided that the above
@@ -18,6 +18,12 @@
18 18
19#define FUDGE 2 19#define FUDGE 2
20 20
21static void ath9k_reset_beacon_status(struct ath_softc *sc)
22{
23 sc->beacon.tx_processed = false;
24 sc->beacon.tx_last = false;
25}
26
21/* 27/*
22 * This function will modify certain transmit queue properties depending on 28 * This function will modify certain transmit queue properties depending on
23 * the operating mode of the station (AP or AdHoc). Parameters are AIFS 29 * the operating mode of the station (AP or AdHoc). Parameters are AIFS
@@ -28,7 +34,7 @@ int ath_beaconq_config(struct ath_softc *sc)
28 struct ath_hw *ah = sc->sc_ah; 34 struct ath_hw *ah = sc->sc_ah;
29 struct ath_common *common = ath9k_hw_common(ah); 35 struct ath_common *common = ath9k_hw_common(ah);
30 struct ath9k_tx_queue_info qi, qi_be; 36 struct ath9k_tx_queue_info qi, qi_be;
31 int qnum; 37 struct ath_txq *txq;
32 38
33 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); 39 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
34 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 40 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -38,16 +44,16 @@ int ath_beaconq_config(struct ath_softc *sc)
38 qi.tqi_cwmax = 0; 44 qi.tqi_cwmax = 0;
39 } else { 45 } else {
40 /* Adhoc mode; important thing is to use 2x cwmin. */ 46 /* Adhoc mode; important thing is to use 2x cwmin. */
41 qnum = sc->tx.hwq_map[WME_AC_BE]; 47 txq = sc->tx.txq_map[WME_AC_BE];
42 ath9k_hw_get_txq_props(ah, qnum, &qi_be); 48 ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
43 qi.tqi_aifs = qi_be.tqi_aifs; 49 qi.tqi_aifs = qi_be.tqi_aifs;
44 qi.tqi_cwmin = 4*qi_be.tqi_cwmin; 50 qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
45 qi.tqi_cwmax = qi_be.tqi_cwmax; 51 qi.tqi_cwmax = qi_be.tqi_cwmax;
46 } 52 }
47 53
48 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { 54 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
49 ath_print(common, ATH_DBG_FATAL, 55 ath_err(common,
50 "Unable to update h/w beacon queue parameters\n"); 56 "Unable to update h/w beacon queue parameters\n");
51 return 0; 57 return 0;
52 } else { 58 } else {
53 ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); 59 ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
@@ -57,8 +63,8 @@ int ath_beaconq_config(struct ath_softc *sc)
57 63
58/* 64/*
59 * Associates the beacon frame buffer with a transmit descriptor. Will set 65 * Associates the beacon frame buffer with a transmit descriptor. Will set
60 * up all required antenna switch parameters, rate codes, and channel flags. 66 * up rate codes, and channel flags. Beacons are always sent out at the
61 * Beacons are always sent out at the lowest rate, and are not retried. 67 * lowest rate, and are not retried.
62*/ 68*/
63static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, 69static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
64 struct ath_buf *bf, int rateidx) 70 struct ath_buf *bf, int rateidx)
@@ -68,20 +74,16 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
68 struct ath_common *common = ath9k_hw_common(ah); 74 struct ath_common *common = ath9k_hw_common(ah);
69 struct ath_desc *ds; 75 struct ath_desc *ds;
70 struct ath9k_11n_rate_series series[4]; 76 struct ath9k_11n_rate_series series[4];
71 int flags, antenna, ctsrate = 0, ctsduration = 0; 77 int flags, ctsrate = 0, ctsduration = 0;
72 struct ieee80211_supported_band *sband; 78 struct ieee80211_supported_band *sband;
73 u8 rate = 0; 79 u8 rate = 0;
74 80
81 ath9k_reset_beacon_status(sc);
82
75 ds = bf->bf_desc; 83 ds = bf->bf_desc;
76 flags = ATH9K_TXDESC_NOACK; 84 flags = ATH9K_TXDESC_NOACK;
77 85
78 ds->ds_link = 0; 86 ds->ds_link = 0;
79 /*
80 * Switch antenna every beacon.
81 * Should only switch every beacon period, not for every SWBA
82 * XXX assumes two antennae
83 */
84 antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
85 87
86 sband = &sc->sbands[common->hw->conf.channel->band]; 88 sband = &sc->sbands[common->hw->conf.channel->band];
87 rate = sband->bitrates[rateidx].hw_value; 89 rate = sband->bitrates[rateidx].hw_value;
@@ -103,17 +105,35 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
103 memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); 105 memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
104 series[0].Tries = 1; 106 series[0].Tries = 1;
105 series[0].Rate = rate; 107 series[0].Rate = rate;
106 series[0].ChSel = common->tx_chainmask; 108 series[0].ChSel = ath_txchainmask_reduction(sc,
109 common->tx_chainmask, series[0].Rate);
107 series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; 110 series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
108 ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, 111 ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
109 series, 4, 0); 112 series, 4, 0);
110} 113}
111 114
115static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
116{
117 struct ath_softc *sc = hw->priv;
118 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
119 struct ath_tx_control txctl;
120
121 memset(&txctl, 0, sizeof(struct ath_tx_control));
122 txctl.txq = sc->beacon.cabq;
123
124 ath_dbg(common, ATH_DBG_XMIT,
125 "transmitting CABQ packet, skb: %p\n", skb);
126
127 if (ath_tx_start(hw, skb, &txctl) != 0) {
128 ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n");
129 dev_kfree_skb_any(skb);
130 }
131}
132
112static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, 133static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
113 struct ieee80211_vif *vif) 134 struct ieee80211_vif *vif)
114{ 135{
115 struct ath_wiphy *aphy = hw->priv; 136 struct ath_softc *sc = hw->priv;
116 struct ath_softc *sc = aphy->sc;
117 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 137 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
118 struct ath_buf *bf; 138 struct ath_buf *bf;
119 struct ath_vif *avp; 139 struct ath_vif *avp;
@@ -122,13 +142,12 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
122 struct ieee80211_tx_info *info; 142 struct ieee80211_tx_info *info;
123 int cabq_depth; 143 int cabq_depth;
124 144
125 if (aphy->state != ATH_WIPHY_ACTIVE) 145 ath9k_reset_beacon_status(sc);
126 return NULL;
127 146
128 avp = (void *)vif->drv_priv; 147 avp = (void *)vif->drv_priv;
129 cabq = sc->beacon.cabq; 148 cabq = sc->beacon.cabq;
130 149
131 if (avp->av_bcbuf == NULL) 150 if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active)
132 return NULL; 151 return NULL;
133 152
134 /* Release the old beacon first */ 153 /* Release the old beacon first */
@@ -136,9 +155,10 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
136 bf = avp->av_bcbuf; 155 bf = avp->av_bcbuf;
137 skb = bf->bf_mpdu; 156 skb = bf->bf_mpdu;
138 if (skb) { 157 if (skb) {
139 dma_unmap_single(sc->dev, bf->bf_dmacontext, 158 dma_unmap_single(sc->dev, bf->bf_buf_addr,
140 skb->len, DMA_TO_DEVICE); 159 skb->len, DMA_TO_DEVICE);
141 dev_kfree_skb_any(skb); 160 dev_kfree_skb_any(skb);
161 bf->bf_buf_addr = 0;
142 } 162 }
143 163
144 /* Get a new beacon from mac80211 */ 164 /* Get a new beacon from mac80211 */
@@ -162,14 +182,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
162 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); 182 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
163 } 183 }
164 184
165 bf->bf_buf_addr = bf->bf_dmacontext = 185 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
166 dma_map_single(sc->dev, skb->data, 186 skb->len, DMA_TO_DEVICE);
167 skb->len, DMA_TO_DEVICE);
168 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { 187 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
169 dev_kfree_skb_any(skb); 188 dev_kfree_skb_any(skb);
170 bf->bf_mpdu = NULL; 189 bf->bf_mpdu = NULL;
171 ath_print(common, ATH_DBG_FATAL, 190 bf->bf_buf_addr = 0;
172 "dma_mapping_error on beaconing\n"); 191 ath_err(common, "dma_mapping_error on beaconing\n");
173 return NULL; 192 return NULL;
174 } 193 }
175 194
@@ -189,8 +208,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
189 208
190 if (skb && cabq_depth) { 209 if (skb && cabq_depth) {
191 if (sc->nvifs > 1) { 210 if (sc->nvifs > 1) {
192 ath_print(common, ATH_DBG_BEACON, 211 ath_dbg(common, ATH_DBG_BEACON,
193 "Flushing previous cabq traffic\n"); 212 "Flushing previous cabq traffic\n");
194 ath_draintxq(sc, cabq, false); 213 ath_draintxq(sc, cabq, false);
195 } 214 }
196 } 215 }
@@ -205,13 +224,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
205 return bf; 224 return bf;
206} 225}
207 226
208int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) 227int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
209{ 228{
210 struct ath_softc *sc = aphy->sc;
211 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 229 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
212 struct ath_vif *avp; 230 struct ath_vif *avp;
213 struct ath_buf *bf; 231 struct ath_buf *bf;
214 struct sk_buff *skb; 232 struct sk_buff *skb;
233 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
215 __le64 tstamp; 234 __le64 tstamp;
216 235
217 avp = (void *)vif->drv_priv; 236 avp = (void *)vif->drv_priv;
@@ -224,9 +243,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
224 struct ath_buf, list); 243 struct ath_buf, list);
225 list_del(&avp->av_bcbuf->list); 244 list_del(&avp->av_bcbuf->list);
226 245
227 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || 246 if (ath9k_uses_beacons(vif->type)) {
228 sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
229 sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
230 int slot; 247 int slot;
231 /* 248 /*
232 * Assign the vif to a beacon xmit slot. As 249 * Assign the vif to a beacon xmit slot. As
@@ -236,6 +253,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
236 for (slot = 0; slot < ATH_BCBUF; slot++) 253 for (slot = 0; slot < ATH_BCBUF; slot++)
237 if (sc->beacon.bslot[slot] == NULL) { 254 if (sc->beacon.bslot[slot] == NULL) {
238 avp->av_bslot = slot; 255 avp->av_bslot = slot;
256 avp->is_bslot_active = false;
239 257
240 /* NB: keep looking for a double slot */ 258 /* NB: keep looking for a double slot */
241 if (slot == 0 || !sc->beacon.bslot[slot-1]) 259 if (slot == 0 || !sc->beacon.bslot[slot-1])
@@ -243,7 +261,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
243 } 261 }
244 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); 262 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
245 sc->beacon.bslot[avp->av_bslot] = vif; 263 sc->beacon.bslot[avp->av_bslot] = vif;
246 sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
247 sc->nbcnvifs++; 264 sc->nbcnvifs++;
248 } 265 }
249 } 266 }
@@ -252,27 +269,26 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
252 bf = avp->av_bcbuf; 269 bf = avp->av_bcbuf;
253 if (bf->bf_mpdu != NULL) { 270 if (bf->bf_mpdu != NULL) {
254 skb = bf->bf_mpdu; 271 skb = bf->bf_mpdu;
255 dma_unmap_single(sc->dev, bf->bf_dmacontext, 272 dma_unmap_single(sc->dev, bf->bf_buf_addr,
256 skb->len, DMA_TO_DEVICE); 273 skb->len, DMA_TO_DEVICE);
257 dev_kfree_skb_any(skb); 274 dev_kfree_skb_any(skb);
258 bf->bf_mpdu = NULL; 275 bf->bf_mpdu = NULL;
276 bf->bf_buf_addr = 0;
259 } 277 }
260 278
261 /* NB: the beacon data buffer must be 32-bit aligned. */ 279 /* NB: the beacon data buffer must be 32-bit aligned. */
262 skb = ieee80211_beacon_get(sc->hw, vif); 280 skb = ieee80211_beacon_get(sc->hw, vif);
263 if (skb == NULL) { 281 if (skb == NULL)
264 ath_print(common, ATH_DBG_BEACON, "cannot get skb\n");
265 return -ENOMEM; 282 return -ENOMEM;
266 }
267 283
268 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; 284 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
269 sc->beacon.bc_tstamp = le64_to_cpu(tstamp); 285 sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp);
270 /* Calculate a TSF adjustment factor required for staggered beacons. */ 286 /* Calculate a TSF adjustment factor required for staggered beacons. */
271 if (avp->av_bslot > 0) { 287 if (avp->av_bslot > 0) {
272 u64 tsfadjust; 288 u64 tsfadjust;
273 int intval; 289 int intval;
274 290
275 intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; 291 intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
276 292
277 /* 293 /*
278 * Calculate the TSF offset for this beacon slot, i.e., the 294 * Calculate the TSF offset for this beacon slot, i.e., the
@@ -282,13 +298,12 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
282 * adjustment. Other slots are adjusted to get the timestamp 298 * adjustment. Other slots are adjusted to get the timestamp
283 * close to the TBTT for the BSS. 299 * close to the TBTT for the BSS.
284 */ 300 */
285 tsfadjust = intval * avp->av_bslot / ATH_BCBUF; 301 tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF;
286 avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); 302 avp->tsf_adjust = cpu_to_le64(tsfadjust);
287 303
288 ath_print(common, ATH_DBG_BEACON, 304 ath_dbg(common, ATH_DBG_BEACON,
289 "stagger beacons, bslot %d intval " 305 "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
290 "%u tsfadjust %llu\n", 306 avp->av_bslot, intval, (unsigned long long)tsfadjust);
291 avp->av_bslot, intval, (unsigned long long)tsfadjust);
292 307
293 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = 308 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
294 avp->tsf_adjust; 309 avp->tsf_adjust;
@@ -296,16 +311,16 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
296 avp->tsf_adjust = cpu_to_le64(0); 311 avp->tsf_adjust = cpu_to_le64(0);
297 312
298 bf->bf_mpdu = skb; 313 bf->bf_mpdu = skb;
299 bf->bf_buf_addr = bf->bf_dmacontext = 314 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
300 dma_map_single(sc->dev, skb->data, 315 skb->len, DMA_TO_DEVICE);
301 skb->len, DMA_TO_DEVICE);
302 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { 316 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
303 dev_kfree_skb_any(skb); 317 dev_kfree_skb_any(skb);
304 bf->bf_mpdu = NULL; 318 bf->bf_mpdu = NULL;
305 ath_print(common, ATH_DBG_FATAL, 319 bf->bf_buf_addr = 0;
306 "dma_mapping_error on beacon alloc\n"); 320 ath_err(common, "dma_mapping_error on beacon alloc\n");
307 return -ENOMEM; 321 return -ENOMEM;
308 } 322 }
323 avp->is_bslot_active = true;
309 324
310 return 0; 325 return 0;
311} 326}
@@ -315,19 +330,21 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
315 if (avp->av_bcbuf != NULL) { 330 if (avp->av_bcbuf != NULL) {
316 struct ath_buf *bf; 331 struct ath_buf *bf;
317 332
333 avp->is_bslot_active = false;
318 if (avp->av_bslot != -1) { 334 if (avp->av_bslot != -1) {
319 sc->beacon.bslot[avp->av_bslot] = NULL; 335 sc->beacon.bslot[avp->av_bslot] = NULL;
320 sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
321 sc->nbcnvifs--; 336 sc->nbcnvifs--;
337 avp->av_bslot = -1;
322 } 338 }
323 339
324 bf = avp->av_bcbuf; 340 bf = avp->av_bcbuf;
325 if (bf->bf_mpdu != NULL) { 341 if (bf->bf_mpdu != NULL) {
326 struct sk_buff *skb = bf->bf_mpdu; 342 struct sk_buff *skb = bf->bf_mpdu;
327 dma_unmap_single(sc->dev, bf->bf_dmacontext, 343 dma_unmap_single(sc->dev, bf->bf_buf_addr,
328 skb->len, DMA_TO_DEVICE); 344 skb->len, DMA_TO_DEVICE);
329 dev_kfree_skb_any(skb); 345 dev_kfree_skb_any(skb);
330 bf->bf_mpdu = NULL; 346 bf->bf_mpdu = NULL;
347 bf->bf_buf_addr = 0;
331 } 348 }
332 list_add_tail(&bf->list, &sc->beacon.bbuf); 349 list_add_tail(&bf->list, &sc->beacon.bbuf);
333 350
@@ -338,15 +355,13 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
338void ath_beacon_tasklet(unsigned long data) 355void ath_beacon_tasklet(unsigned long data)
339{ 356{
340 struct ath_softc *sc = (struct ath_softc *)data; 357 struct ath_softc *sc = (struct ath_softc *)data;
358 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
341 struct ath_hw *ah = sc->sc_ah; 359 struct ath_hw *ah = sc->sc_ah;
342 struct ath_common *common = ath9k_hw_common(ah); 360 struct ath_common *common = ath9k_hw_common(ah);
343 struct ath_buf *bf = NULL; 361 struct ath_buf *bf = NULL;
344 struct ieee80211_vif *vif; 362 struct ieee80211_vif *vif;
345 struct ath_wiphy *aphy;
346 int slot; 363 int slot;
347 u32 bfaddr, bc = 0, tsftu; 364 u32 bfaddr, bc = 0;
348 u64 tsf;
349 u16 intval;
350 365
351 /* 366 /*
352 * Check if the previous beacon has gone out. If 367 * Check if the previous beacon has gone out. If
@@ -358,60 +373,65 @@ void ath_beacon_tasklet(unsigned long data)
358 if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { 373 if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
359 sc->beacon.bmisscnt++; 374 sc->beacon.bmisscnt++;
360 375
361 if (sc->beacon.bmisscnt < BSTUCK_THRESH) { 376 if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
362 ath_print(common, ATH_DBG_BEACON, 377 ath_dbg(common, ATH_DBG_BSTUCK,
363 "missed %u consecutive beacons\n", 378 "missed %u consecutive beacons\n",
364 sc->beacon.bmisscnt); 379 sc->beacon.bmisscnt);
380 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
381 if (sc->beacon.bmisscnt > 3)
382 ath9k_hw_bstuck_nfcal(ah);
365 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { 383 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
366 ath_print(common, ATH_DBG_BEACON, 384 ath_dbg(common, ATH_DBG_BSTUCK,
367 "beacon is officially stuck\n"); 385 "beacon is officially stuck\n");
368 sc->sc_flags |= SC_OP_TSF_RESET; 386 sc->sc_flags |= SC_OP_TSF_RESET;
369 ath_reset(sc, false); 387 ath_reset(sc, true);
370 } 388 }
371 389
372 return; 390 return;
373 } 391 }
374 392
375 if (sc->beacon.bmisscnt != 0) {
376 ath_print(common, ATH_DBG_BEACON,
377 "resume beacon xmit after %u misses\n",
378 sc->beacon.bmisscnt);
379 sc->beacon.bmisscnt = 0;
380 }
381
382 /* 393 /*
383 * Generate beacon frames. we are sending frames 394 * Generate beacon frames. we are sending frames
384 * staggered so calculate the slot for this frame based 395 * staggered so calculate the slot for this frame based
385 * on the tsf to safeguard against missing an swba. 396 * on the tsf to safeguard against missing an swba.
386 */ 397 */
387 398
388 intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
389 399
390 tsf = ath9k_hw_gettsf64(ah); 400 if (ah->opmode == NL80211_IFTYPE_AP) {
391 tsftu = TSF_TO_TU(tsf>>32, tsf); 401 u16 intval;
392 slot = ((tsftu % intval) * ATH_BCBUF) / intval; 402 u32 tsftu;
393 /* 403 u64 tsf;
394 * Reverse the slot order to get slot 0 on the TBTT offset that does 404
395 * not require TSF adjustment and other slots adding 405 intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
396 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with 406 tsf = ath9k_hw_gettsf64(ah);
397 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. 407 tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
398 * and slot 0 is at correct offset to TBTT. 408 tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
399 */ 409 slot = (tsftu % (intval * ATH_BCBUF)) / intval;
400 slot = ATH_BCBUF - slot - 1; 410 vif = sc->beacon.bslot[slot];
401 vif = sc->beacon.bslot[slot]; 411
402 aphy = sc->beacon.bslot_aphy[slot]; 412 ath_dbg(common, ATH_DBG_BEACON,
413 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
414 slot, tsf, tsftu / ATH_BCBUF, intval, vif);
415 } else {
416 slot = 0;
417 vif = sc->beacon.bslot[slot];
418 }
403 419
404 ath_print(common, ATH_DBG_BEACON,
405 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
406 slot, tsf, tsftu, intval, vif);
407 420
408 bfaddr = 0; 421 bfaddr = 0;
409 if (vif) { 422 if (vif) {
410 bf = ath_beacon_generate(aphy->hw, vif); 423 bf = ath_beacon_generate(sc->hw, vif);
411 if (bf != NULL) { 424 if (bf != NULL) {
412 bfaddr = bf->bf_daddr; 425 bfaddr = bf->bf_daddr;
413 bc = 1; 426 bc = 1;
414 } 427 }
428
429 if (sc->beacon.bmisscnt != 0) {
430 ath_dbg(common, ATH_DBG_BSTUCK,
431 "resume beacon xmit after %u misses\n",
432 sc->beacon.bmisscnt);
433 sc->beacon.bmisscnt = 0;
434 }
415 } 435 }
416 436
417 /* 437 /*
@@ -439,16 +459,6 @@ void ath_beacon_tasklet(unsigned long data)
439 sc->beacon.updateslot = OK; 459 sc->beacon.updateslot = OK;
440 } 460 }
441 if (bfaddr != 0) { 461 if (bfaddr != 0) {
442 /*
443 * Stop any current dma and put the new frame(s) on the queue.
444 * This should never fail since we check above that no frames
445 * are still pending on the queue.
446 */
447 if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
448 ath_print(common, ATH_DBG_FATAL,
449 "beacon queue %u did not stop?\n", sc->beacon.beaconq);
450 }
451
452 /* NB: cabq traffic should already be queued and primed */ 462 /* NB: cabq traffic should already be queued and primed */
453 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); 463 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
454 ath9k_hw_txstart(ah, sc->beacon.beaconq); 464 ath9k_hw_txstart(ah, sc->beacon.beaconq);
@@ -461,13 +471,17 @@ static void ath9k_beacon_init(struct ath_softc *sc,
461 u32 next_beacon, 471 u32 next_beacon,
462 u32 beacon_period) 472 u32 beacon_period)
463{ 473{
464 if (beacon_period & ATH9K_BEACON_RESET_TSF) 474 if (sc->sc_flags & SC_OP_TSF_RESET) {
465 ath9k_ps_wakeup(sc); 475 ath9k_ps_wakeup(sc);
476 ath9k_hw_reset_tsf(sc->sc_ah);
477 }
466 478
467 ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); 479 ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period);
468 480
469 if (beacon_period & ATH9K_BEACON_RESET_TSF) 481 if (sc->sc_flags & SC_OP_TSF_RESET) {
470 ath9k_ps_restore(sc); 482 ath9k_ps_restore(sc);
483 sc->sc_flags &= ~SC_OP_TSF_RESET;
484 }
471} 485}
472 486
473/* 487/*
@@ -482,32 +496,23 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
482 u32 nexttbtt, intval; 496 u32 nexttbtt, intval;
483 497
484 /* NB: the beacon interval is kept internally in TU's */ 498 /* NB: the beacon interval is kept internally in TU's */
485 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; 499 intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
486 intval /= ATH_BCBUF; /* for staggered beacons */ 500 intval /= ATH_BCBUF; /* for staggered beacons */
487 nexttbtt = intval; 501 nexttbtt = intval;
488 502
489 if (sc->sc_flags & SC_OP_TSF_RESET)
490 intval |= ATH9K_BEACON_RESET_TSF;
491
492 /* 503 /*
493 * In AP mode we enable the beacon timers and SWBA interrupts to 504 * In AP mode we enable the beacon timers and SWBA interrupts to
494 * prepare beacon frames. 505 * prepare beacon frames.
495 */ 506 */
496 intval |= ATH9K_BEACON_ENA;
497 ah->imask |= ATH9K_INT_SWBA; 507 ah->imask |= ATH9K_INT_SWBA;
498 ath_beaconq_config(sc); 508 ath_beaconq_config(sc);
499 509
500 /* Set the computed AP beacon timers */ 510 /* Set the computed AP beacon timers */
501 511
502 ath9k_hw_set_interrupts(ah, 0); 512 ath9k_hw_disable_interrupts(ah);
503 ath9k_beacon_init(sc, nexttbtt, intval); 513 ath9k_beacon_init(sc, nexttbtt, intval);
504 sc->beacon.bmisscnt = 0; 514 sc->beacon.bmisscnt = 0;
505 ath9k_hw_set_interrupts(ah, ah->imask); 515 ath9k_hw_set_interrupts(ah, ah->imask);
506
507 /* Clear the reset TSF flag, so that subsequent beacon updation
508 will not reset the HW TSF. */
509
510 sc->sc_flags &= ~SC_OP_TSF_RESET;
511} 516}
512 517
513/* 518/*
@@ -532,8 +537,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
532 537
533 /* No need to configure beacon if we are not associated */ 538 /* No need to configure beacon if we are not associated */
534 if (!common->curaid) { 539 if (!common->curaid) {
535 ath_print(common, ATH_DBG_BEACON, 540 ath_dbg(common, ATH_DBG_BEACON,
536 "STA is not yet associated..skipping beacon config\n"); 541 "STA is not yet associated..skipping beacon config\n");
537 return; 542 return;
538 } 543 }
539 544
@@ -545,8 +550,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
545 * last beacon we received (which may be none). 550 * last beacon we received (which may be none).
546 */ 551 */
547 dtimperiod = conf->dtim_period; 552 dtimperiod = conf->dtim_period;
548 if (dtimperiod <= 0) /* NB: 0 if not known */
549 dtimperiod = 1;
550 dtimcount = conf->dtim_count; 553 dtimcount = conf->dtim_count;
551 if (dtimcount >= dtimperiod) /* NB: sanity check */ 554 if (dtimcount >= dtimperiod) /* NB: sanity check */
552 dtimcount = 0; 555 dtimcount = 0;
@@ -554,8 +557,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
554 cfpcount = 0; 557 cfpcount = 0;
555 558
556 sleepduration = conf->listen_interval * intval; 559 sleepduration = conf->listen_interval * intval;
557 if (sleepduration <= 0)
558 sleepduration = intval;
559 560
560 /* 561 /*
561 * Pull nexttbtt forward to reflect the current 562 * Pull nexttbtt forward to reflect the current
@@ -626,89 +627,135 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
626 /* TSF out of range threshold fixed at 1 second */ 627 /* TSF out of range threshold fixed at 1 second */
627 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; 628 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
628 629
629 ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); 630 ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
630 ath_print(common, ATH_DBG_BEACON, 631 ath_dbg(common, ATH_DBG_BEACON,
631 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", 632 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
632 bs.bs_bmissthreshold, bs.bs_sleepduration, 633 bs.bs_bmissthreshold, bs.bs_sleepduration,
633 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); 634 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
634 635
635 /* Set the computed STA beacon timers */ 636 /* Set the computed STA beacon timers */
636 637
637 ath9k_hw_set_interrupts(ah, 0); 638 ath9k_hw_disable_interrupts(ah);
638 ath9k_hw_set_sta_beacon_timers(ah, &bs); 639 ath9k_hw_set_sta_beacon_timers(ah, &bs);
639 ah->imask |= ATH9K_INT_BMISS; 640 ah->imask |= ATH9K_INT_BMISS;
640 ath9k_hw_set_interrupts(ah, ah->imask); 641
642 /*
643 * If the beacon config is called beacause of TSFOOR,
644 * Interrupts will be enabled back at the end of ath9k_tasklet
645 */
646 if (!(sc->ps_flags & PS_TSFOOR_SYNC))
647 ath9k_hw_set_interrupts(ah, ah->imask);
641} 648}
642 649
643static void ath_beacon_config_adhoc(struct ath_softc *sc, 650static void ath_beacon_config_adhoc(struct ath_softc *sc,
644 struct ath_beacon_config *conf, 651 struct ath_beacon_config *conf)
645 struct ieee80211_vif *vif)
646{ 652{
647 struct ath_hw *ah = sc->sc_ah; 653 struct ath_hw *ah = sc->sc_ah;
648 struct ath_common *common = ath9k_hw_common(ah); 654 struct ath_common *common = ath9k_hw_common(ah);
649 u64 tsf; 655 u32 tsf, delta, intval, nexttbtt;
650 u32 tsftu, intval, nexttbtt;
651
652 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
653
654 656
655 /* Pull nexttbtt forward to reflect the current TSF */ 657 ath9k_reset_beacon_status(sc);
656 658
657 nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); 659 tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
658 if (nexttbtt == 0) 660 intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
659 nexttbtt = intval;
660 else if (intval)
661 nexttbtt = roundup(nexttbtt, intval);
662 661
663 tsf = ath9k_hw_gettsf64(ah); 662 if (!sc->beacon.bc_tstamp)
664 tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; 663 nexttbtt = tsf + intval;
665 do { 664 else {
666 nexttbtt += intval; 665 if (tsf > sc->beacon.bc_tstamp)
667 } while (nexttbtt < tsftu); 666 delta = (tsf - sc->beacon.bc_tstamp);
667 else
668 delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
669 nexttbtt = tsf + intval - (delta % intval);
670 }
668 671
669 ath_print(common, ATH_DBG_BEACON, 672 ath_dbg(common, ATH_DBG_BEACON,
670 "IBSS nexttbtt %u intval %u (%u)\n", 673 "IBSS nexttbtt %u intval %u (%u)\n",
671 nexttbtt, intval, conf->beacon_interval); 674 nexttbtt, intval, conf->beacon_interval);
672 675
673 /* 676 /*
674 * In IBSS mode enable the beacon timers but only enable SWBA interrupts 677 * In IBSS mode enable the beacon timers but only enable SWBA interrupts
675 * if we need to manually prepare beacon frames. Otherwise we use a 678 * if we need to manually prepare beacon frames. Otherwise we use a
676 * self-linked tx descriptor and let the hardware deal with things. 679 * self-linked tx descriptor and let the hardware deal with things.
677 */ 680 */
678 intval |= ATH9K_BEACON_ENA;
679 ah->imask |= ATH9K_INT_SWBA; 681 ah->imask |= ATH9K_INT_SWBA;
680 682
681 ath_beaconq_config(sc); 683 ath_beaconq_config(sc);
682 684
683 /* Set the computed ADHOC beacon timers */ 685 /* Set the computed ADHOC beacon timers */
684 686
685 ath9k_hw_set_interrupts(ah, 0); 687 ath9k_hw_disable_interrupts(ah);
686 ath9k_beacon_init(sc, nexttbtt, intval); 688 ath9k_beacon_init(sc, nexttbtt, intval);
687 sc->beacon.bmisscnt = 0; 689 sc->beacon.bmisscnt = 0;
688 ath9k_hw_set_interrupts(ah, ah->imask); 690 /*
691 * If the beacon config is called beacause of TSFOOR,
692 * Interrupts will be enabled back at the end of ath9k_tasklet
693 */
694 if (!(sc->ps_flags & PS_TSFOOR_SYNC))
695 ath9k_hw_set_interrupts(ah, ah->imask);
689} 696}
690 697
691void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) 698static bool ath9k_allow_beacon_config(struct ath_softc *sc,
699 struct ieee80211_vif *vif)
692{ 700{
693 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 701 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
694 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 702 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
695 enum nl80211_iftype iftype; 703 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
704 struct ath_vif *avp = (void *)vif->drv_priv;
696 705
697 /* Setup the beacon configuration parameters */ 706 /*
698 if (vif) { 707 * Can not have different beacon interval on multiple
699 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 708 * AP interface case
709 */
710 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
711 (sc->nbcnvifs > 1) &&
712 (vif->type == NL80211_IFTYPE_AP) &&
713 (cur_conf->beacon_interval != bss_conf->beacon_int)) {
714 ath_dbg(common, ATH_DBG_CONFIG,
715 "Changing beacon interval of multiple \
716 AP interfaces !\n");
717 return false;
718 }
719 /*
720 * Can not configure station vif's beacon config
721 * while on AP opmode
722 */
723 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
724 (vif->type != NL80211_IFTYPE_AP)) {
725 ath_dbg(common, ATH_DBG_CONFIG,
726 "STA vif's beacon not allowed on AP mode\n");
727 return false;
728 }
729 /*
730 * Do not allow beacon config if HW was already configured
731 * with another STA vif
732 */
733 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
734 (vif->type == NL80211_IFTYPE_STATION) &&
735 (sc->sc_flags & SC_OP_BEACONS) &&
736 !avp->primary_sta_vif) {
737 ath_dbg(common, ATH_DBG_CONFIG,
738 "Beacon already configured for a station interface\n");
739 return false;
740 }
741 return true;
742}
700 743
701 iftype = vif->type; 744void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
745{
746 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
747 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
702 748
703 cur_conf->beacon_interval = bss_conf->beacon_int; 749 if (!ath9k_allow_beacon_config(sc, vif))
704 cur_conf->dtim_period = bss_conf->dtim_period; 750 return;
705 cur_conf->listen_interval = 1; 751
706 cur_conf->dtim_count = 1; 752 /* Setup the beacon configuration parameters */
707 cur_conf->bmiss_timeout = 753 cur_conf->beacon_interval = bss_conf->beacon_int;
708 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 754 cur_conf->dtim_period = bss_conf->dtim_period;
709 } else { 755 cur_conf->listen_interval = 1;
710 iftype = sc->sc_ah->opmode; 756 cur_conf->dtim_count = 1;
711 } 757 cur_conf->bmiss_timeout =
758 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
712 759
713 /* 760 /*
714 * It looks like mac80211 may end up using beacon interval of zero in 761 * It looks like mac80211 may end up using beacon interval of zero in
@@ -719,22 +766,80 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
719 if (cur_conf->beacon_interval == 0) 766 if (cur_conf->beacon_interval == 0)
720 cur_conf->beacon_interval = 100; 767 cur_conf->beacon_interval = 100;
721 768
722 switch (iftype) { 769 /*
770 * We don't parse dtim period from mac80211 during the driver
771 * initialization as it breaks association with hidden-ssid
772 * AP and it causes latency in roaming
773 */
774 if (cur_conf->dtim_period == 0)
775 cur_conf->dtim_period = 1;
776
777 ath_set_beacon(sc);
778}
779
780static bool ath_has_valid_bslot(struct ath_softc *sc)
781{
782 struct ath_vif *avp;
783 int slot;
784 bool found = false;
785
786 for (slot = 0; slot < ATH_BCBUF; slot++) {
787 if (sc->beacon.bslot[slot]) {
788 avp = (void *)sc->beacon.bslot[slot]->drv_priv;
789 if (avp->is_bslot_active) {
790 found = true;
791 break;
792 }
793 }
794 }
795 return found;
796}
797
798
799void ath_set_beacon(struct ath_softc *sc)
800{
801 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
802 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
803
804 switch (sc->sc_ah->opmode) {
723 case NL80211_IFTYPE_AP: 805 case NL80211_IFTYPE_AP:
724 ath_beacon_config_ap(sc, cur_conf); 806 if (ath_has_valid_bslot(sc))
807 ath_beacon_config_ap(sc, cur_conf);
725 break; 808 break;
726 case NL80211_IFTYPE_ADHOC: 809 case NL80211_IFTYPE_ADHOC:
727 case NL80211_IFTYPE_MESH_POINT: 810 case NL80211_IFTYPE_MESH_POINT:
728 ath_beacon_config_adhoc(sc, cur_conf, vif); 811 ath_beacon_config_adhoc(sc, cur_conf);
729 break; 812 break;
730 case NL80211_IFTYPE_STATION: 813 case NL80211_IFTYPE_STATION:
731 ath_beacon_config_sta(sc, cur_conf); 814 ath_beacon_config_sta(sc, cur_conf);
732 break; 815 break;
733 default: 816 default:
734 ath_print(common, ATH_DBG_CONFIG, 817 ath_dbg(common, ATH_DBG_CONFIG,
735 "Unsupported beaconing mode\n"); 818 "Unsupported beaconing mode\n");
736 return; 819 return;
737 } 820 }
738 821
739 sc->sc_flags |= SC_OP_BEACONS; 822 sc->sc_flags |= SC_OP_BEACONS;
740} 823}
824
825void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
826{
827 struct ath_hw *ah = sc->sc_ah;
828
829 if (!ath_has_valid_bslot(sc))
830 return;
831
832 ath9k_ps_wakeup(sc);
833 if (status) {
834 /* Re-enable beaconing */
835 ah->imask |= ATH9K_INT_SWBA;
836 ath9k_hw_set_interrupts(ah, ah->imask);
837 } else {
838 /* Disable SWBA interrupt */
839 ah->imask &= ~ATH9K_INT_SWBA;
840 ath9k_hw_set_interrupts(ah, ah->imask);
841 tasklet_kill(&sc->bcon_tasklet);
842 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
843 }
844 ath9k_ps_restore(sc);
845}