• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2008-2011 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <linux/dma-mapping.h>
18 #include "ath9k.h"
19 
20 #define FUDGE 2
21 
ath9k_reset_beacon_status(struct ath_softc * sc)22 static void ath9k_reset_beacon_status(struct ath_softc *sc)
23 {
24 	sc->beacon.tx_processed = false;
25 	sc->beacon.tx_last = false;
26 }
27 
28 /*
29  *  This function will modify certain transmit queue properties depending on
30  *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
31  *  settings and channel width min/max
32 */
ath9k_beaconq_config(struct ath_softc * sc)33 static void ath9k_beaconq_config(struct ath_softc *sc)
34 {
35 	struct ath_hw *ah = sc->sc_ah;
36 	struct ath_common *common = ath9k_hw_common(ah);
37 	struct ath9k_tx_queue_info qi, qi_be;
38 	struct ath_txq *txq;
39 
40 	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
41 
42 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
43 	    sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
44 		/* Always burst out beacon and CAB traffic. */
45 		qi.tqi_aifs = 1;
46 		qi.tqi_cwmin = 0;
47 		qi.tqi_cwmax = 0;
48 	} else {
49 		/* Adhoc mode; important thing is to use 2x cwmin. */
50 		txq = sc->tx.txq_map[IEEE80211_AC_BE];
51 		ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
52 		qi.tqi_aifs = qi_be.tqi_aifs;
53 		if (ah->slottime == 20)
54 			qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
55 		else
56 			qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
57 		qi.tqi_cwmax = qi_be.tqi_cwmax;
58 	}
59 
60 	if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
61 		ath_err(common, "Unable to update h/w beacon queue parameters\n");
62 	} else {
63 		ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
64 	}
65 }
66 
67 /*
68  *  Associates the beacon frame buffer with a transmit descriptor.  Will set
69  *  up rate codes, and channel flags. Beacons are always sent out at the
70  *  lowest rate, and are not retried.
71 */
ath9k_beacon_setup(struct ath_softc * sc,struct ieee80211_vif * vif,struct ath_buf * bf,int rateidx)72 static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
73 			     struct ath_buf *bf, int rateidx)
74 {
75 	struct sk_buff *skb = bf->bf_mpdu;
76 	struct ath_hw *ah = sc->sc_ah;
77 	struct ath_common *common = ath9k_hw_common(ah);
78 	struct ath_tx_info info;
79 	struct ieee80211_supported_band *sband;
80 	u8 chainmask = ah->txchainmask;
81 	u8 i, rate = 0;
82 
83 	sband = &common->sbands[sc->cur_chandef.chan->band];
84 	rate = sband->bitrates[rateidx].hw_value;
85 	if (vif->bss_conf.use_short_preamble)
86 		rate |= sband->bitrates[rateidx].hw_value_short;
87 
88 	memset(&info, 0, sizeof(info));
89 	info.pkt_len = skb->len + FCS_LEN;
90 	info.type = ATH9K_PKT_TYPE_BEACON;
91 	for (i = 0; i < 4; i++)
92 		info.txpower[i] = MAX_RATE_POWER;
93 	info.keyix = ATH9K_TXKEYIX_INVALID;
94 	info.keytype = ATH9K_KEY_TYPE_CLEAR;
95 	info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK;
96 
97 	info.buf_addr[0] = bf->bf_buf_addr;
98 	info.buf_len[0] = roundup(skb->len, 4);
99 
100 	info.is_first = true;
101 	info.is_last = true;
102 
103 	info.qcu = sc->beacon.beaconq;
104 
105 	info.rates[0].Tries = 1;
106 	info.rates[0].Rate = rate;
107 	info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
108 
109 	ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
110 }
111 
ath9k_beacon_generate(struct ieee80211_hw * hw,struct ieee80211_vif * vif)112 static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
113 					     struct ieee80211_vif *vif)
114 {
115 	struct ath_softc *sc = hw->priv;
116 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
117 	struct ath_buf *bf;
118 	struct ath_vif *avp = (void *)vif->drv_priv;
119 	struct sk_buff *skb;
120 	struct ath_txq *cabq = sc->beacon.cabq;
121 	struct ieee80211_tx_info *info;
122 	struct ieee80211_mgmt *mgmt_hdr;
123 	int cabq_depth;
124 
125 	if (avp->av_bcbuf == NULL)
126 		return NULL;
127 
128 	bf = avp->av_bcbuf;
129 	skb = bf->bf_mpdu;
130 	if (skb) {
131 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
132 				 skb->len, DMA_TO_DEVICE);
133 		dev_kfree_skb_any(skb);
134 		bf->bf_buf_addr = 0;
135 		bf->bf_mpdu = NULL;
136 	}
137 
138 	skb = ieee80211_beacon_get(hw, vif);
139 	if (skb == NULL)
140 		return NULL;
141 
142 	bf->bf_mpdu = skb;
143 
144 	mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
145 	mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
146 
147 	info = IEEE80211_SKB_CB(skb);
148 
149 	ath_assign_seq(common, skb);
150 
151 	/* Always assign NOA attr when MCC enabled */
152 	if (ath9k_is_chanctx_enabled())
153 		ath9k_beacon_add_noa(sc, avp, skb);
154 
155 	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
156 					 skb->len, DMA_TO_DEVICE);
157 	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
158 		dev_kfree_skb_any(skb);
159 		bf->bf_mpdu = NULL;
160 		bf->bf_buf_addr = 0;
161 		ath_err(common, "dma_mapping_error on beaconing\n");
162 		return NULL;
163 	}
164 
165 	skb = ieee80211_get_buffered_bc(hw, vif);
166 
167 	/*
168 	 * if the CABQ traffic from previous DTIM is pending and the current
169 	 *  beacon is also a DTIM.
170 	 *  1) if there is only one vif let the cab traffic continue.
171 	 *  2) if there are more than one vif and we are using staggered
172 	 *     beacons, then drain the cabq by dropping all the frames in
173 	 *     the cabq so that the current vifs cab traffic can be scheduled.
174 	 */
175 	spin_lock_bh(&cabq->axq_lock);
176 	cabq_depth = cabq->axq_depth;
177 	spin_unlock_bh(&cabq->axq_lock);
178 
179 	if (skb && cabq_depth) {
180 		if (sc->cur_chan->nvifs > 1) {
181 			ath_dbg(common, BEACON,
182 				"Flushing previous cabq traffic\n");
183 			ath_draintxq(sc, cabq);
184 		}
185 	}
186 
187 	ath9k_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
188 
189 	if (skb)
190 		ath_tx_cabq(hw, vif, skb);
191 
192 	return bf;
193 }
194 
ath9k_beacon_assign_slot(struct ath_softc * sc,struct ieee80211_vif * vif)195 void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
196 {
197 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
198 	struct ath_vif *avp = (void *)vif->drv_priv;
199 	int slot;
200 
201 	avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list);
202 	list_del(&avp->av_bcbuf->list);
203 
204 	for (slot = 0; slot < ATH_BCBUF; slot++) {
205 		if (sc->beacon.bslot[slot] == NULL) {
206 			avp->av_bslot = slot;
207 			break;
208 		}
209 	}
210 
211 	sc->beacon.bslot[avp->av_bslot] = vif;
212 
213 	ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
214 		avp->av_bslot);
215 }
216 
ath9k_beacon_remove_slot(struct ath_softc * sc,struct ieee80211_vif * vif)217 void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
218 {
219 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
220 	struct ath_vif *avp = (void *)vif->drv_priv;
221 	struct ath_buf *bf = avp->av_bcbuf;
222 
223 	ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
224 		avp->av_bslot);
225 
226 	tasklet_disable(&sc->bcon_tasklet);
227 
228 	if (bf && bf->bf_mpdu) {
229 		struct sk_buff *skb = bf->bf_mpdu;
230 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
231 				 skb->len, DMA_TO_DEVICE);
232 		dev_kfree_skb_any(skb);
233 		bf->bf_mpdu = NULL;
234 		bf->bf_buf_addr = 0;
235 	}
236 
237 	avp->av_bcbuf = NULL;
238 	sc->beacon.bslot[avp->av_bslot] = NULL;
239 	list_add_tail(&bf->list, &sc->beacon.bbuf);
240 
241 	tasklet_enable(&sc->bcon_tasklet);
242 }
243 
ath9k_beacon_ensure_primary_slot(struct ath_softc * sc)244 void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc)
245 {
246 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
247 	struct ieee80211_vif *vif;
248 	struct ath_vif *avp;
249 	s64 tsfadjust;
250 	u32 offset;
251 	int first_slot = ATH_BCBUF;
252 	int slot;
253 
254 	tasklet_disable(&sc->bcon_tasklet);
255 
256 	/* Find first taken slot. */
257 	for (slot = 0; slot < ATH_BCBUF; slot++) {
258 		if (sc->beacon.bslot[slot]) {
259 			first_slot = slot;
260 			break;
261 		}
262 	}
263 	if (first_slot == 0)
264 		goto out;
265 
266 	/* Re-enumarate all slots, moving them forward. */
267 	for (slot = 0; slot < ATH_BCBUF; slot++) {
268 		if (slot + first_slot < ATH_BCBUF) {
269 			vif = sc->beacon.bslot[slot + first_slot];
270 			sc->beacon.bslot[slot] = vif;
271 
272 			if (vif) {
273 				avp = (void *)vif->drv_priv;
274 				avp->av_bslot = slot;
275 			}
276 		} else {
277 			sc->beacon.bslot[slot] = NULL;
278 		}
279 	}
280 
281 	vif = sc->beacon.bslot[0];
282 	if (WARN_ON(!vif))
283 		goto out;
284 
285 	/* Get the tsf_adjust value for the new first slot. */
286 	avp = (void *)vif->drv_priv;
287 	tsfadjust = le64_to_cpu(avp->tsf_adjust);
288 
289 	ath_dbg(common, CONFIG,
290 		"Adjusting global TSF after beacon slot reassignment: %lld\n",
291 		(signed long long)tsfadjust);
292 
293 	/* Modify TSF as required and update the HW. */
294 	avp->chanctx->tsf_val += tsfadjust;
295 	if (sc->cur_chan == avp->chanctx) {
296 		offset = ath9k_hw_get_tsf_offset(&avp->chanctx->tsf_ts, NULL);
297 		ath9k_hw_settsf64(sc->sc_ah, avp->chanctx->tsf_val + offset);
298 	}
299 
300 	/* The slots tsf_adjust will be updated by ath9k_beacon_config later. */
301 
302 out:
303 	tasklet_enable(&sc->bcon_tasklet);
304 }
305 
ath9k_beacon_choose_slot(struct ath_softc * sc)306 static int ath9k_beacon_choose_slot(struct ath_softc *sc)
307 {
308 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
309 	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
310 	u16 intval;
311 	u32 tsftu;
312 	u64 tsf;
313 	int slot;
314 
315 	if (sc->sc_ah->opmode != NL80211_IFTYPE_AP &&
316 	    sc->sc_ah->opmode != NL80211_IFTYPE_MESH_POINT) {
317 		ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
318 			ath9k_hw_gettsf64(sc->sc_ah));
319 		return 0;
320 	}
321 
322 	intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
323 	tsf = ath9k_hw_gettsf64(sc->sc_ah);
324 	tsf += TU_TO_USEC(sc->sc_ah->config.sw_beacon_response_time);
325 	tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
326 	slot = (tsftu % (intval * ATH_BCBUF)) / intval;
327 
328 	ath_dbg(common, BEACON, "slot: %d tsf: %llu tsftu: %u\n",
329 		slot, tsf, tsftu / ATH_BCBUF);
330 
331 	return slot;
332 }
333 
ath9k_set_tsfadjust(struct ath_softc * sc,struct ath_beacon_config * cur_conf)334 static void ath9k_set_tsfadjust(struct ath_softc *sc,
335 				struct ath_beacon_config *cur_conf)
336 {
337 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
338 	s64 tsfadjust;
339 	int slot;
340 
341 	for (slot = 0; slot < ATH_BCBUF; slot++) {
342 		struct ath_vif *avp;
343 
344 		if (!sc->beacon.bslot[slot])
345 			continue;
346 
347 		avp = (void *)sc->beacon.bslot[slot]->drv_priv;
348 
349 		/* tsf_adjust is added to the TSF value. We send out the
350 		 * beacon late, so need to adjust the TSF starting point to be
351 		 * later in time (i.e. the theoretical first beacon has a TSF
352 		 * of 0 after correction).
353 		 */
354 		tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
355 		tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
356 		avp->tsf_adjust = cpu_to_le64(tsfadjust);
357 
358 		ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
359 			(signed long long)tsfadjust, avp->av_bslot);
360 	}
361 }
362 
ath9k_csa_is_finished(struct ath_softc * sc,struct ieee80211_vif * vif)363 bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
364 {
365 	if (!vif || !vif->csa_active)
366 		return false;
367 
368 	if (!ieee80211_beacon_cntdwn_is_complete(vif))
369 		return false;
370 
371 	ieee80211_csa_finish(vif);
372 	return true;
373 }
374 
ath9k_csa_update_vif(void * data,u8 * mac,struct ieee80211_vif * vif)375 static void ath9k_csa_update_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
376 {
377 	struct ath_softc *sc = data;
378 	ath9k_csa_is_finished(sc, vif);
379 }
380 
ath9k_csa_update(struct ath_softc * sc)381 void ath9k_csa_update(struct ath_softc *sc)
382 {
383 	ieee80211_iterate_active_interfaces_atomic(sc->hw,
384 						   IEEE80211_IFACE_ITER_NORMAL,
385 						   ath9k_csa_update_vif, sc);
386 }
387 
ath9k_beacon_tasklet(struct tasklet_struct * t)388 void ath9k_beacon_tasklet(struct tasklet_struct *t)
389 {
390 	struct ath_softc *sc = from_tasklet(sc, t, bcon_tasklet);
391 	struct ath_hw *ah = sc->sc_ah;
392 	struct ath_common *common = ath9k_hw_common(ah);
393 	struct ath_buf *bf = NULL;
394 	struct ieee80211_vif *vif;
395 	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
396 	int slot;
397 
398 	if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
399 		ath_dbg(common, RESET,
400 			"reset work is pending, skip beaconing now\n");
401 		return;
402 	}
403 
404 	/*
405 	 * Check if the previous beacon has gone out.  If
406 	 * not don't try to post another, skip this period
407 	 * and wait for the next.  Missed beacons indicate
408 	 * a problem and should not occur.  If we miss too
409 	 * many consecutive beacons reset the device.
410 	 */
411 	if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
412 		sc->beacon.bmisscnt++;
413 
414 		ath9k_hw_check_nav(ah);
415 
416 		/*
417 		 * If the previous beacon has not been transmitted
418 		 * and a MAC/BB hang has been identified, return
419 		 * here because a chip reset would have been
420 		 * initiated.
421 		 */
422 		if (!ath_hw_check(sc))
423 			return;
424 
425 		if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
426 			ath_dbg(common, BSTUCK,
427 				"missed %u consecutive beacons\n",
428 				sc->beacon.bmisscnt);
429 			ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
430 			if (sc->beacon.bmisscnt > 3)
431 				ath9k_hw_bstuck_nfcal(ah);
432 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
433 			ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
434 			sc->beacon.bmisscnt = 0;
435 			ath9k_queue_reset(sc, RESET_TYPE_BEACON_STUCK);
436 		}
437 
438 		return;
439 	}
440 
441 	slot = ath9k_beacon_choose_slot(sc);
442 	vif = sc->beacon.bslot[slot];
443 
444 	/* EDMA devices check that in the tx completion function. */
445 	if (!edma) {
446 		if (ath9k_is_chanctx_enabled()) {
447 			ath_chanctx_beacon_sent_ev(sc,
448 					  ATH_CHANCTX_EVENT_BEACON_SENT);
449 		}
450 
451 		if (ath9k_csa_is_finished(sc, vif))
452 			return;
453 	}
454 
455 	if (!vif || !vif->bss_conf.enable_beacon)
456 		return;
457 
458 	if (ath9k_is_chanctx_enabled()) {
459 		ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_BEACON_PREPARE);
460 	}
461 
462 	bf = ath9k_beacon_generate(sc->hw, vif);
463 
464 	if (sc->beacon.bmisscnt != 0) {
465 		ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
466 			sc->beacon.bmisscnt);
467 		sc->beacon.bmisscnt = 0;
468 	}
469 
470 	/*
471 	 * Handle slot time change when a non-ERP station joins/leaves
472 	 * an 11g network.  The 802.11 layer notifies us via callback,
473 	 * we mark updateslot, then wait one beacon before effecting
474 	 * the change.  This gives associated stations at least one
475 	 * beacon interval to note the state change.
476 	 *
477 	 * NB: The slot time change state machine is clocked according
478 	 *     to whether we are bursting or staggering beacons.  We
479 	 *     recognize the request to update and record the current
480 	 *     slot then don't transition until that slot is reached
481 	 *     again.  If we miss a beacon for that slot then we'll be
482 	 *     slow to transition but we'll be sure at least one beacon
483 	 *     interval has passed.  When bursting slot is always left
484 	 *     set to ATH_BCBUF so this check is a noop.
485 	 */
486 	if (sc->beacon.updateslot == UPDATE) {
487 		sc->beacon.updateslot = COMMIT;
488 		sc->beacon.slotupdate = slot;
489 	} else if (sc->beacon.updateslot == COMMIT &&
490 		   sc->beacon.slotupdate == slot) {
491 		ah->slottime = sc->beacon.slottime;
492 		ath9k_hw_init_global_settings(ah);
493 		sc->beacon.updateslot = OK;
494 	}
495 
496 	if (bf) {
497 		ath9k_reset_beacon_status(sc);
498 
499 		ath_dbg(common, BEACON,
500 			"Transmitting beacon for slot: %d\n", slot);
501 
502 		/* NB: cabq traffic should already be queued and primed */
503 		ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
504 
505 		if (!edma)
506 			ath9k_hw_txstart(ah, sc->beacon.beaconq);
507 	}
508 }
509 
510 /*
511  * Both nexttbtt and intval have to be in usecs.
512  */
ath9k_beacon_init(struct ath_softc * sc,u32 nexttbtt,u32 intval)513 static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
514 			      u32 intval)
515 {
516 	struct ath_hw *ah = sc->sc_ah;
517 
518 	ath9k_hw_disable_interrupts(ah);
519 	ath9k_beaconq_config(sc);
520 	ath9k_hw_beaconinit(ah, nexttbtt, intval);
521 	ah->imask |= ATH9K_INT_SWBA;
522 	sc->beacon.bmisscnt = 0;
523 	ath9k_hw_set_interrupts(ah);
524 	ath9k_hw_enable_interrupts(ah);
525 }
526 
ath9k_beacon_stop(struct ath_softc * sc)527 static void ath9k_beacon_stop(struct ath_softc *sc)
528 {
529 	ath9k_hw_disable_interrupts(sc->sc_ah);
530 	sc->sc_ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
531 	sc->beacon.bmisscnt = 0;
532 	ath9k_hw_set_interrupts(sc->sc_ah);
533 	ath9k_hw_enable_interrupts(sc->sc_ah);
534 }
535 
536 /*
537  * For multi-bss ap support beacons are either staggered evenly over N slots or
538  * burst together.  For the former arrange for the SWBA to be delivered for each
539  * slot. Slots that are not occupied will generate nothing.
540  */
ath9k_beacon_config_ap(struct ath_softc * sc,struct ath_beacon_config * conf)541 static void ath9k_beacon_config_ap(struct ath_softc *sc,
542 				   struct ath_beacon_config *conf)
543 {
544 	struct ath_hw *ah = sc->sc_ah;
545 
546 	ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF);
547 	ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
548 }
549 
ath9k_beacon_config_sta(struct ath_hw * ah,struct ath_beacon_config * conf)550 static void ath9k_beacon_config_sta(struct ath_hw *ah,
551 				    struct ath_beacon_config *conf)
552 {
553 	struct ath9k_beacon_state bs;
554 
555 	if (ath9k_cmn_beacon_config_sta(ah, conf, &bs) == -EPERM)
556 		return;
557 
558 	ath9k_hw_disable_interrupts(ah);
559 	ath9k_hw_set_sta_beacon_timers(ah, &bs);
560 	ah->imask |= ATH9K_INT_BMISS;
561 
562 	ath9k_hw_set_interrupts(ah);
563 	ath9k_hw_enable_interrupts(ah);
564 }
565 
ath9k_beacon_config_adhoc(struct ath_softc * sc,struct ath_beacon_config * conf)566 static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
567 				      struct ath_beacon_config *conf)
568 {
569 	struct ath_hw *ah = sc->sc_ah;
570 	struct ath_common *common = ath9k_hw_common(ah);
571 
572 	ath9k_reset_beacon_status(sc);
573 
574 	ath9k_cmn_beacon_config_adhoc(ah, conf);
575 
576 	ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
577 
578 	/*
579 	 * Set the global 'beacon has been configured' flag for the
580 	 * joiner case in IBSS mode.
581 	 */
582 	if (!conf->ibss_creator && conf->enable_beacon)
583 		set_bit(ATH_OP_BEACONS, &common->op_flags);
584 }
585 
ath9k_cache_beacon_config(struct ath_softc * sc,struct ath_chanctx * ctx,struct ieee80211_bss_conf * bss_conf)586 static void ath9k_cache_beacon_config(struct ath_softc *sc,
587 				      struct ath_chanctx *ctx,
588 				      struct ieee80211_bss_conf *bss_conf)
589 {
590 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
591 	struct ath_beacon_config *cur_conf = &ctx->beacon;
592 
593 	ath_dbg(common, BEACON,
594 		"Caching beacon data for BSS: %pM\n", bss_conf->bssid);
595 
596 	cur_conf->beacon_interval = bss_conf->beacon_int;
597 	cur_conf->dtim_period = bss_conf->dtim_period;
598 	cur_conf->dtim_count = 1;
599 	cur_conf->ibss_creator = bss_conf->ibss_creator;
600 
601 	/*
602 	 * It looks like mac80211 may end up using beacon interval of zero in
603 	 * some cases (at least for mesh point). Avoid getting into an
604 	 * infinite loop by using a bit safer value instead. To be safe,
605 	 * do sanity check on beacon interval for all operating modes.
606 	 */
607 	if (cur_conf->beacon_interval == 0)
608 		cur_conf->beacon_interval = 100;
609 
610 	cur_conf->bmiss_timeout =
611 		ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
612 
613 	/*
614 	 * We don't parse dtim period from mac80211 during the driver
615 	 * initialization as it breaks association with hidden-ssid
616 	 * AP and it causes latency in roaming
617 	 */
618 	if (cur_conf->dtim_period == 0)
619 		cur_conf->dtim_period = 1;
620 
621 	ath9k_set_tsfadjust(sc, cur_conf);
622 }
623 
ath9k_beacon_config(struct ath_softc * sc,struct ieee80211_vif * main_vif,bool beacons)624 void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
625 			 bool beacons)
626 {
627 	struct ath_hw *ah = sc->sc_ah;
628 	struct ath_common *common = ath9k_hw_common(ah);
629 	struct ath_vif *avp;
630 	struct ath_chanctx *ctx;
631 	struct ath_beacon_config *cur_conf;
632 	unsigned long flags;
633 	bool enabled;
634 	bool skip_beacon = false;
635 
636 	if (!beacons) {
637 		clear_bit(ATH_OP_BEACONS, &common->op_flags);
638 		ath9k_beacon_stop(sc);
639 		return;
640 	}
641 
642 	if (WARN_ON(!main_vif))
643 		return;
644 
645 	avp = (void *)main_vif->drv_priv;
646 	ctx = avp->chanctx;
647 	cur_conf = &ctx->beacon;
648 	enabled = cur_conf->enable_beacon;
649 	cur_conf->enable_beacon = beacons;
650 
651 	if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
652 		ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
653 
654 		ath9k_set_beacon(sc);
655 		set_bit(ATH_OP_BEACONS, &common->op_flags);
656 		return;
657 	}
658 
659 	/* Update the beacon configuration. */
660 	ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
661 
662 	/*
663 	 * Configure the HW beacon registers only when we have a valid
664 	 * beacon interval.
665 	 */
666 	if (cur_conf->beacon_interval) {
667 		/* Special case to sync the TSF when joining an existing IBSS.
668 		 * This is only done if no AP interface is active.
669 		 * Note that mac80211 always resets the TSF when creating a new
670 		 * IBSS interface.
671 		 */
672 		if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC &&
673 		    !enabled && beacons && !main_vif->bss_conf.ibss_creator) {
674 			spin_lock_irqsave(&sc->sc_pm_lock, flags);
675 			sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
676 			spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
677 			skip_beacon = true;
678 		}
679 
680 		/*
681 		 * Do not set the ATH_OP_BEACONS flag for IBSS joiner mode
682 		 * here, it is done in ath9k_beacon_config_adhoc().
683 		 */
684 		if (beacons && !skip_beacon) {
685 			set_bit(ATH_OP_BEACONS, &common->op_flags);
686 			ath9k_set_beacon(sc);
687 		} else {
688 			clear_bit(ATH_OP_BEACONS, &common->op_flags);
689 			ath9k_beacon_stop(sc);
690 		}
691 	} else {
692 		clear_bit(ATH_OP_BEACONS, &common->op_flags);
693 		ath9k_beacon_stop(sc);
694 	}
695 }
696 
ath9k_set_beacon(struct ath_softc * sc)697 void ath9k_set_beacon(struct ath_softc *sc)
698 {
699 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
700 	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
701 
702 	switch (sc->sc_ah->opmode) {
703 	case NL80211_IFTYPE_AP:
704 	case NL80211_IFTYPE_MESH_POINT:
705 		ath9k_beacon_config_ap(sc, cur_conf);
706 		break;
707 	case NL80211_IFTYPE_ADHOC:
708 		ath9k_beacon_config_adhoc(sc, cur_conf);
709 		break;
710 	case NL80211_IFTYPE_STATION:
711 		ath9k_beacon_config_sta(sc->sc_ah, cur_conf);
712 		break;
713 	default:
714 		ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
715 		return;
716 	}
717 }
718