if_ath_beacon.c revision 235680
1/*- 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_beacon.c 235680 2012-05-20 04:14:29Z adrian $"); 32 33/* 34 * Driver for the Atheros Wireless LAN controller. 35 * 36 * This software is derived from work of Atsushi Onoe; his contribution 37 * is greatly appreciated. 38 */ 39 40#include "opt_inet.h" 41#include "opt_ath.h" 42/* 43 * This is needed for register operations which are performed 44 * by the driver - eg, calls to ath_hal_gettsf32(). 45 * 46 * It's also required for any AH_DEBUG checks in here, eg the 47 * module dependencies. 48 */ 49#include "opt_ah.h" 50#include "opt_wlan.h" 51 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/sysctl.h> 55#include <sys/mbuf.h> 56#include <sys/malloc.h> 57#include <sys/lock.h> 58#include <sys/mutex.h> 59#include <sys/kernel.h> 60#include <sys/socket.h> 61#include <sys/sockio.h> 62#include <sys/errno.h> 63#include <sys/callout.h> 64#include <sys/bus.h> 65#include <sys/endian.h> 66#include <sys/kthread.h> 67#include <sys/taskqueue.h> 68#include <sys/priv.h> 69#include <sys/module.h> 70#include <sys/ktr.h> 71#include <sys/smp.h> /* for mp_ncpus */ 72 73#include <machine/bus.h> 74 75#include <net/if.h> 76#include <net/if_dl.h> 77#include <net/if_media.h> 78#include <net/if_types.h> 79#include <net/if_arp.h> 80#include <net/ethernet.h> 81#include <net/if_llc.h> 82 83#include <net80211/ieee80211_var.h> 84#include <net80211/ieee80211_regdomain.h> 85#ifdef IEEE80211_SUPPORT_SUPERG 86#include <net80211/ieee80211_superg.h> 87#endif 88 89#include <net/bpf.h> 90 91#ifdef INET 92#include <netinet/in.h> 93#include <netinet/if_ether.h> 94#endif 95 96#include <dev/ath/if_athvar.h> 97 98#include <dev/ath/if_ath_debug.h> 99#include <dev/ath/if_ath_misc.h> 100#include <dev/ath/if_ath_tx.h> 101#include <dev/ath/if_ath_beacon.h> 102 103#ifdef ATH_TX99_DIAG 104#include <dev/ath/ath_tx99/ath_tx99.h> 105#endif 106 107/* 108 * Setup a h/w transmit queue for beacons. 109 */ 110int 111ath_beaconq_setup(struct ath_hal *ah) 112{ 113 HAL_TXQ_INFO qi; 114 115 memset(&qi, 0, sizeof(qi)); 116 qi.tqi_aifs = HAL_TXQ_USEDEFAULT; 117 qi.tqi_cwmin = HAL_TXQ_USEDEFAULT; 118 qi.tqi_cwmax = HAL_TXQ_USEDEFAULT; 119 /* NB: for dynamic turbo, don't enable any other interrupts */ 120 qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; 121 return ath_hal_setuptxqueue(ah, HAL_TX_QUEUE_BEACON, &qi); 122} 123 124/* 125 * Setup the transmit queue parameters for the beacon queue. 126 */ 127int 128ath_beaconq_config(struct ath_softc *sc) 129{ 130#define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1) 131 struct ieee80211com *ic = sc->sc_ifp->if_l2com; 132 struct ath_hal *ah = sc->sc_ah; 133 HAL_TXQ_INFO qi; 134 135 ath_hal_gettxqueueprops(ah, sc->sc_bhalq, &qi); 136 if (ic->ic_opmode == IEEE80211_M_HOSTAP || 137 ic->ic_opmode == IEEE80211_M_MBSS) { 138 /* 139 * Always burst out beacon and CAB traffic. 140 */ 141 qi.tqi_aifs = ATH_BEACON_AIFS_DEFAULT; 142 qi.tqi_cwmin = ATH_BEACON_CWMIN_DEFAULT; 143 qi.tqi_cwmax = ATH_BEACON_CWMAX_DEFAULT; 144 } else { 145 struct wmeParams *wmep = 146 &ic->ic_wme.wme_chanParams.cap_wmeParams[WME_AC_BE]; 147 /* 148 * Adhoc mode; important thing is to use 2x cwmin. 149 */ 150 qi.tqi_aifs = wmep->wmep_aifsn; 151 qi.tqi_cwmin = 2*ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin); 152 qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax); 153 } 154 155 if (!ath_hal_settxqueueprops(ah, sc->sc_bhalq, &qi)) { 156 device_printf(sc->sc_dev, "unable to update parameters for " 157 "beacon hardware queue!\n"); 158 return 0; 159 } else { 160 ath_hal_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */ 161 return 1; 162 } 163#undef ATH_EXPONENT_TO_VALUE 164} 165 166/* 167 * Allocate and setup an initial beacon frame. 168 */ 169int 170ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni) 171{ 172 struct ieee80211vap *vap = ni->ni_vap; 173 struct ath_vap *avp = ATH_VAP(vap); 174 struct ath_buf *bf; 175 struct mbuf *m; 176 int error; 177 178 bf = avp->av_bcbuf; 179 DPRINTF(sc, ATH_DEBUG_NODE, "%s: bf_m=%p, bf_node=%p\n", 180 __func__, bf->bf_m, bf->bf_node); 181 if (bf->bf_m != NULL) { 182 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); 183 m_freem(bf->bf_m); 184 bf->bf_m = NULL; 185 } 186 if (bf->bf_node != NULL) { 187 ieee80211_free_node(bf->bf_node); 188 bf->bf_node = NULL; 189 } 190 191 /* 192 * NB: the beacon data buffer must be 32-bit aligned; 193 * we assume the mbuf routines will return us something 194 * with this alignment (perhaps should assert). 195 */ 196 m = ieee80211_beacon_alloc(ni, &avp->av_boff); 197 if (m == NULL) { 198 device_printf(sc->sc_dev, "%s: cannot get mbuf\n", __func__); 199 sc->sc_stats.ast_be_nombuf++; 200 return ENOMEM; 201 } 202 error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m, 203 bf->bf_segs, &bf->bf_nseg, 204 BUS_DMA_NOWAIT); 205 if (error != 0) { 206 device_printf(sc->sc_dev, 207 "%s: cannot map mbuf, bus_dmamap_load_mbuf_sg returns %d\n", 208 __func__, error); 209 m_freem(m); 210 return error; 211 } 212 213 /* 214 * Calculate a TSF adjustment factor required for staggered 215 * beacons. Note that we assume the format of the beacon 216 * frame leaves the tstamp field immediately following the 217 * header. 218 */ 219 if (sc->sc_stagbeacons && avp->av_bslot > 0) { 220 uint64_t tsfadjust; 221 struct ieee80211_frame *wh; 222 223 /* 224 * The beacon interval is in TU's; the TSF is in usecs. 225 * We figure out how many TU's to add to align the timestamp 226 * then convert to TSF units and handle byte swapping before 227 * inserting it in the frame. The hardware will then add this 228 * each time a beacon frame is sent. Note that we align vap's 229 * 1..N and leave vap 0 untouched. This means vap 0 has a 230 * timestamp in one beacon interval while the others get a 231 * timstamp aligned to the next interval. 232 */ 233 tsfadjust = ni->ni_intval * 234 (ATH_BCBUF - avp->av_bslot) / ATH_BCBUF; 235 tsfadjust = htole64(tsfadjust << 10); /* TU -> TSF */ 236 237 DPRINTF(sc, ATH_DEBUG_BEACON, 238 "%s: %s beacons bslot %d intval %u tsfadjust %llu\n", 239 __func__, sc->sc_stagbeacons ? "stagger" : "burst", 240 avp->av_bslot, ni->ni_intval, 241 (long long unsigned) le64toh(tsfadjust)); 242 243 wh = mtod(m, struct ieee80211_frame *); 244 memcpy(&wh[1], &tsfadjust, sizeof(tsfadjust)); 245 } 246 bf->bf_m = m; 247 bf->bf_node = ieee80211_ref_node(ni); 248 249 return 0; 250} 251 252/* 253 * Setup the beacon frame for transmit. 254 */ 255static void 256ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf) 257{ 258#define USE_SHPREAMBLE(_ic) \ 259 (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\ 260 == IEEE80211_F_SHPREAMBLE) 261 struct ieee80211_node *ni = bf->bf_node; 262 struct ieee80211com *ic = ni->ni_ic; 263 struct mbuf *m = bf->bf_m; 264 struct ath_hal *ah = sc->sc_ah; 265 struct ath_desc *ds; 266 int flags, antenna; 267 const HAL_RATE_TABLE *rt; 268 u_int8_t rix, rate; 269 270 DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: m %p len %u\n", 271 __func__, m, m->m_len); 272 273 /* setup descriptors */ 274 ds = bf->bf_desc; 275 bf->bf_last = bf; 276 bf->bf_lastds = ds; 277 278 flags = HAL_TXDESC_NOACK; 279 if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) { 280 ds->ds_link = bf->bf_daddr; /* self-linked */ 281 flags |= HAL_TXDESC_VEOL; 282 /* 283 * Let hardware handle antenna switching. 284 */ 285 antenna = sc->sc_txantenna; 286 } else { 287 ds->ds_link = 0; 288 /* 289 * Switch antenna every 4 beacons. 290 * XXX assumes two antenna 291 */ 292 if (sc->sc_txantenna != 0) 293 antenna = sc->sc_txantenna; 294 else if (sc->sc_stagbeacons && sc->sc_nbcnvaps != 0) 295 antenna = ((sc->sc_stats.ast_be_xmit / sc->sc_nbcnvaps) & 4 ? 2 : 1); 296 else 297 antenna = (sc->sc_stats.ast_be_xmit & 4 ? 2 : 1); 298 } 299 300 KASSERT(bf->bf_nseg == 1, 301 ("multi-segment beacon frame; nseg %u", bf->bf_nseg)); 302 ds->ds_data = bf->bf_segs[0].ds_addr; 303 /* 304 * Calculate rate code. 305 * XXX everything at min xmit rate 306 */ 307 rix = 0; 308 rt = sc->sc_currates; 309 rate = rt->info[rix].rateCode; 310 if (USE_SHPREAMBLE(ic)) 311 rate |= rt->info[rix].shortPreamble; 312 ath_hal_setuptxdesc(ah, ds 313 , m->m_len + IEEE80211_CRC_LEN /* frame length */ 314 , sizeof(struct ieee80211_frame)/* header length */ 315 , HAL_PKT_TYPE_BEACON /* Atheros packet type */ 316 , ni->ni_txpower /* txpower XXX */ 317 , rate, 1 /* series 0 rate/tries */ 318 , HAL_TXKEYIX_INVALID /* no encryption */ 319 , antenna /* antenna mode */ 320 , flags /* no ack, veol for beacons */ 321 , 0 /* rts/cts rate */ 322 , 0 /* rts/cts duration */ 323 ); 324 /* NB: beacon's BufLen must be a multiple of 4 bytes */ 325 ath_hal_filltxdesc(ah, ds 326 , roundup(m->m_len, 4) /* buffer length */ 327 , AH_TRUE /* first segment */ 328 , AH_TRUE /* last segment */ 329 , ds /* first descriptor */ 330 ); 331#if 0 332 ath_desc_swap(ds); 333#endif 334#undef USE_SHPREAMBLE 335} 336 337void 338ath_beacon_update(struct ieee80211vap *vap, int item) 339{ 340 struct ieee80211_beacon_offsets *bo = &ATH_VAP(vap)->av_boff; 341 342 setbit(bo->bo_flags, item); 343} 344 345/* 346 * Transmit a beacon frame at SWBA. Dynamic updates to the 347 * frame contents are done as needed and the slot time is 348 * also adjusted based on current state. 349 */ 350void 351ath_beacon_proc(void *arg, int pending) 352{ 353 struct ath_softc *sc = arg; 354 struct ath_hal *ah = sc->sc_ah; 355 struct ieee80211vap *vap; 356 struct ath_buf *bf; 357 int slot, otherant; 358 uint32_t bfaddr; 359 360 DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: pending %u\n", 361 __func__, pending); 362 /* 363 * Check if the previous beacon has gone out. If 364 * not don't try to post another, skip this period 365 * and wait for the next. Missed beacons indicate 366 * a problem and should not occur. If we miss too 367 * many consecutive beacons reset the device. 368 */ 369 if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) { 370 sc->sc_bmisscount++; 371 sc->sc_stats.ast_be_missed++; 372 DPRINTF(sc, ATH_DEBUG_BEACON, 373 "%s: missed %u consecutive beacons\n", 374 __func__, sc->sc_bmisscount); 375 if (sc->sc_bmisscount >= ath_bstuck_threshold) 376 taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask); 377 return; 378 } 379 if (sc->sc_bmisscount != 0) { 380 DPRINTF(sc, ATH_DEBUG_BEACON, 381 "%s: resume beacon xmit after %u misses\n", 382 __func__, sc->sc_bmisscount); 383 sc->sc_bmisscount = 0; 384 } 385 386 if (sc->sc_stagbeacons) { /* staggered beacons */ 387 struct ieee80211com *ic = sc->sc_ifp->if_l2com; 388 uint32_t tsftu; 389 390 tsftu = ath_hal_gettsf32(ah) >> 10; 391 /* XXX lintval */ 392 slot = ((tsftu % ic->ic_lintval) * ATH_BCBUF) / ic->ic_lintval; 393 vap = sc->sc_bslot[(slot+1) % ATH_BCBUF]; 394 bfaddr = 0; 395 if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) { 396 bf = ath_beacon_generate(sc, vap); 397 if (bf != NULL) 398 bfaddr = bf->bf_daddr; 399 } 400 } else { /* burst'd beacons */ 401 uint32_t *bflink = &bfaddr; 402 403 for (slot = 0; slot < ATH_BCBUF; slot++) { 404 vap = sc->sc_bslot[slot]; 405 if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) { 406 bf = ath_beacon_generate(sc, vap); 407 if (bf != NULL) { 408 *bflink = bf->bf_daddr; 409 bflink = &bf->bf_desc->ds_link; 410 } 411 } 412 } 413 *bflink = 0; /* terminate list */ 414 } 415 416 /* 417 * Handle slot time change when a non-ERP station joins/leaves 418 * an 11g network. The 802.11 layer notifies us via callback, 419 * we mark updateslot, then wait one beacon before effecting 420 * the change. This gives associated stations at least one 421 * beacon interval to note the state change. 422 */ 423 /* XXX locking */ 424 if (sc->sc_updateslot == UPDATE) { 425 sc->sc_updateslot = COMMIT; /* commit next beacon */ 426 sc->sc_slotupdate = slot; 427 } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) 428 ath_setslottime(sc); /* commit change to h/w */ 429 430 /* 431 * Check recent per-antenna transmit statistics and flip 432 * the default antenna if noticeably more frames went out 433 * on the non-default antenna. 434 * XXX assumes 2 anntenae 435 */ 436 if (!sc->sc_diversity && (!sc->sc_stagbeacons || slot == 0)) { 437 otherant = sc->sc_defant & 1 ? 2 : 1; 438 if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + 2) 439 ath_setdefantenna(sc, otherant); 440 sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0; 441 } 442 443 if (bfaddr != 0) { 444 /* 445 * Stop any current dma and put the new frame on the queue. 446 * This should never fail since we check above that no frames 447 * are still pending on the queue. 448 */ 449 if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) { 450 DPRINTF(sc, ATH_DEBUG_ANY, 451 "%s: beacon queue %u did not stop?\n", 452 __func__, sc->sc_bhalq); 453 } 454 /* NB: cabq traffic should already be queued and primed */ 455 ath_hal_puttxbuf(ah, sc->sc_bhalq, bfaddr); 456 ath_hal_txstart(ah, sc->sc_bhalq); 457 458 sc->sc_stats.ast_be_xmit++; 459 } 460} 461 462struct ath_buf * 463ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) 464{ 465 struct ath_vap *avp = ATH_VAP(vap); 466 struct ath_txq *cabq = sc->sc_cabq; 467 struct ath_buf *bf; 468 struct mbuf *m; 469 int nmcastq, error; 470 471 KASSERT(vap->iv_state >= IEEE80211_S_RUN, 472 ("not running, state %d", vap->iv_state)); 473 KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer")); 474 475 /* 476 * Update dynamic beacon contents. If this returns 477 * non-zero then we need to remap the memory because 478 * the beacon frame changed size (probably because 479 * of the TIM bitmap). 480 */ 481 bf = avp->av_bcbuf; 482 m = bf->bf_m; 483 /* XXX lock mcastq? */ 484 nmcastq = avp->av_mcastq.axq_depth; 485 486 if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, m, nmcastq)) { 487 /* XXX too conservative? */ 488 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); 489 error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m, 490 bf->bf_segs, &bf->bf_nseg, 491 BUS_DMA_NOWAIT); 492 if (error != 0) { 493 if_printf(vap->iv_ifp, 494 "%s: bus_dmamap_load_mbuf_sg failed, error %u\n", 495 __func__, error); 496 return NULL; 497 } 498 } 499 if ((avp->av_boff.bo_tim[4] & 1) && cabq->axq_depth) { 500 DPRINTF(sc, ATH_DEBUG_BEACON, 501 "%s: cabq did not drain, mcastq %u cabq %u\n", 502 __func__, nmcastq, cabq->axq_depth); 503 sc->sc_stats.ast_cabq_busy++; 504 if (sc->sc_nvaps > 1 && sc->sc_stagbeacons) { 505 /* 506 * CABQ traffic from a previous vap is still pending. 507 * We must drain the q before this beacon frame goes 508 * out as otherwise this vap's stations will get cab 509 * frames from a different vap. 510 * XXX could be slow causing us to miss DBA 511 */ 512 ath_tx_draintxq(sc, cabq); 513 } 514 } 515 ath_beacon_setup(sc, bf); 516 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); 517 518 /* 519 * Enable the CAB queue before the beacon queue to 520 * insure cab frames are triggered by this beacon. 521 */ 522 if (avp->av_boff.bo_tim[4] & 1) { 523 struct ath_hal *ah = sc->sc_ah; 524 525 /* NB: only at DTIM */ 526 ATH_TXQ_LOCK(cabq); 527 ATH_TXQ_LOCK(&avp->av_mcastq); 528 if (nmcastq) { 529 struct ath_buf *bfm; 530 531 /* 532 * Move frames from the s/w mcast q to the h/w cab q. 533 * XXX MORE_DATA bit 534 */ 535 bfm = TAILQ_FIRST(&avp->av_mcastq.axq_q); 536 if (cabq->axq_link != NULL) { 537 *cabq->axq_link = bfm->bf_daddr; 538 } else 539 ath_hal_puttxbuf(ah, cabq->axq_qnum, 540 bfm->bf_daddr); 541 ath_txqmove(cabq, &avp->av_mcastq); 542 543 sc->sc_stats.ast_cabq_xmit += nmcastq; 544 } 545 /* NB: gated by beacon so safe to start here */ 546 if (! TAILQ_EMPTY(&(cabq->axq_q))) 547 ath_hal_txstart(ah, cabq->axq_qnum); 548 ATH_TXQ_UNLOCK(&avp->av_mcastq); 549 ATH_TXQ_UNLOCK(cabq); 550 } 551 return bf; 552} 553 554void 555ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap) 556{ 557 struct ath_vap *avp = ATH_VAP(vap); 558 struct ath_hal *ah = sc->sc_ah; 559 struct ath_buf *bf; 560 struct mbuf *m; 561 int error; 562 563 KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer")); 564 565 /* 566 * Update dynamic beacon contents. If this returns 567 * non-zero then we need to remap the memory because 568 * the beacon frame changed size (probably because 569 * of the TIM bitmap). 570 */ 571 bf = avp->av_bcbuf; 572 m = bf->bf_m; 573 if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, m, 0)) { 574 /* XXX too conservative? */ 575 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); 576 error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m, 577 bf->bf_segs, &bf->bf_nseg, 578 BUS_DMA_NOWAIT); 579 if (error != 0) { 580 if_printf(vap->iv_ifp, 581 "%s: bus_dmamap_load_mbuf_sg failed, error %u\n", 582 __func__, error); 583 return; 584 } 585 } 586 ath_beacon_setup(sc, bf); 587 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); 588 589 /* NB: caller is known to have already stopped tx dma */ 590 ath_hal_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr); 591 ath_hal_txstart(ah, sc->sc_bhalq); 592} 593 594/* 595 * Reclaim beacon resources and return buffer to the pool. 596 */ 597void 598ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf) 599{ 600 601 DPRINTF(sc, ATH_DEBUG_NODE, "%s: free bf=%p, bf_m=%p, bf_node=%p\n", 602 __func__, bf, bf->bf_m, bf->bf_node); 603 if (bf->bf_m != NULL) { 604 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); 605 m_freem(bf->bf_m); 606 bf->bf_m = NULL; 607 } 608 if (bf->bf_node != NULL) { 609 ieee80211_free_node(bf->bf_node); 610 bf->bf_node = NULL; 611 } 612 TAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list); 613} 614 615/* 616 * Reclaim beacon resources. 617 */ 618void 619ath_beacon_free(struct ath_softc *sc) 620{ 621 struct ath_buf *bf; 622 623 TAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) { 624 DPRINTF(sc, ATH_DEBUG_NODE, 625 "%s: free bf=%p, bf_m=%p, bf_node=%p\n", 626 __func__, bf, bf->bf_m, bf->bf_node); 627 if (bf->bf_m != NULL) { 628 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); 629 m_freem(bf->bf_m); 630 bf->bf_m = NULL; 631 } 632 if (bf->bf_node != NULL) { 633 ieee80211_free_node(bf->bf_node); 634 bf->bf_node = NULL; 635 } 636 } 637} 638 639/* 640 * Configure the beacon and sleep timers. 641 * 642 * When operating as an AP this resets the TSF and sets 643 * up the hardware to notify us when we need to issue beacons. 644 * 645 * When operating in station mode this sets up the beacon 646 * timers according to the timestamp of the last received 647 * beacon and the current TSF, configures PCF and DTIM 648 * handling, programs the sleep registers so the hardware 649 * will wakeup in time to receive beacons, and configures 650 * the beacon miss handling so we'll receive a BMISS 651 * interrupt when we stop seeing beacons from the AP 652 * we've associated with. 653 */ 654void 655ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) 656{ 657#define TSF_TO_TU(_h,_l) \ 658 ((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10)) 659#define FUDGE 2 660 struct ath_hal *ah = sc->sc_ah; 661 struct ieee80211com *ic = sc->sc_ifp->if_l2com; 662 struct ieee80211_node *ni; 663 u_int32_t nexttbtt, intval, tsftu; 664 u_int64_t tsf; 665 666 if (vap == NULL) 667 vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ 668 ni = ieee80211_ref_node(vap->iv_bss); 669 670 /* extract tstamp from last beacon and convert to TU */ 671 nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4), 672 LE_READ_4(ni->ni_tstamp.data)); 673 if (ic->ic_opmode == IEEE80211_M_HOSTAP || 674 ic->ic_opmode == IEEE80211_M_MBSS) { 675 /* 676 * For multi-bss ap/mesh support beacons are either staggered 677 * evenly over N slots or burst together. For the former 678 * arrange for the SWBA to be delivered for each slot. 679 * Slots that are not occupied will generate nothing. 680 */ 681 /* NB: the beacon interval is kept internally in TU's */ 682 intval = ni->ni_intval & HAL_BEACON_PERIOD; 683 if (sc->sc_stagbeacons) 684 intval /= ATH_BCBUF; 685 } else { 686 /* NB: the beacon interval is kept internally in TU's */ 687 intval = ni->ni_intval & HAL_BEACON_PERIOD; 688 } 689 if (nexttbtt == 0) /* e.g. for ap mode */ 690 nexttbtt = intval; 691 else if (intval) /* NB: can be 0 for monitor mode */ 692 nexttbtt = roundup(nexttbtt, intval); 693 DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", 694 __func__, nexttbtt, intval, ni->ni_intval); 695 if (ic->ic_opmode == IEEE80211_M_STA && !sc->sc_swbmiss) { 696 HAL_BEACON_STATE bs; 697 int dtimperiod, dtimcount; 698 int cfpperiod, cfpcount; 699 700 /* 701 * Setup dtim and cfp parameters according to 702 * last beacon we received (which may be none). 703 */ 704 dtimperiod = ni->ni_dtim_period; 705 if (dtimperiod <= 0) /* NB: 0 if not known */ 706 dtimperiod = 1; 707 dtimcount = ni->ni_dtim_count; 708 if (dtimcount >= dtimperiod) /* NB: sanity check */ 709 dtimcount = 0; /* XXX? */ 710 cfpperiod = 1; /* NB: no PCF support yet */ 711 cfpcount = 0; 712 /* 713 * Pull nexttbtt forward to reflect the current 714 * TSF and calculate dtim+cfp state for the result. 715 */ 716 tsf = ath_hal_gettsf64(ah); 717 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 718 do { 719 nexttbtt += intval; 720 if (--dtimcount < 0) { 721 dtimcount = dtimperiod - 1; 722 if (--cfpcount < 0) 723 cfpcount = cfpperiod - 1; 724 } 725 } while (nexttbtt < tsftu); 726 memset(&bs, 0, sizeof(bs)); 727 bs.bs_intval = intval; 728 bs.bs_nexttbtt = nexttbtt; 729 bs.bs_dtimperiod = dtimperiod*intval; 730 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; 731 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; 732 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; 733 bs.bs_cfpmaxduration = 0; 734#if 0 735 /* 736 * The 802.11 layer records the offset to the DTIM 737 * bitmap while receiving beacons; use it here to 738 * enable h/w detection of our AID being marked in 739 * the bitmap vector (to indicate frames for us are 740 * pending at the AP). 741 * XXX do DTIM handling in s/w to WAR old h/w bugs 742 * XXX enable based on h/w rev for newer chips 743 */ 744 bs.bs_timoffset = ni->ni_timoff; 745#endif 746 /* 747 * Calculate the number of consecutive beacons to miss 748 * before taking a BMISS interrupt. 749 * Note that we clamp the result to at most 10 beacons. 750 */ 751 bs.bs_bmissthreshold = vap->iv_bmissthreshold; 752 if (bs.bs_bmissthreshold > 10) 753 bs.bs_bmissthreshold = 10; 754 else if (bs.bs_bmissthreshold <= 0) 755 bs.bs_bmissthreshold = 1; 756 757 /* 758 * Calculate sleep duration. The configuration is 759 * given in ms. We insure a multiple of the beacon 760 * period is used. Also, if the sleep duration is 761 * greater than the DTIM period then it makes senses 762 * to make it a multiple of that. 763 * 764 * XXX fixed at 100ms 765 */ 766 bs.bs_sleepduration = 767 roundup(IEEE80211_MS_TO_TU(100), bs.bs_intval); 768 if (bs.bs_sleepduration > bs.bs_dtimperiod) 769 bs.bs_sleepduration = roundup(bs.bs_sleepduration, bs.bs_dtimperiod); 770 771 DPRINTF(sc, ATH_DEBUG_BEACON, 772 "%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n" 773 , __func__ 774 , tsf, tsftu 775 , bs.bs_intval 776 , bs.bs_nexttbtt 777 , bs.bs_dtimperiod 778 , bs.bs_nextdtim 779 , bs.bs_bmissthreshold 780 , bs.bs_sleepduration 781 , bs.bs_cfpperiod 782 , bs.bs_cfpmaxduration 783 , bs.bs_cfpnext 784 , bs.bs_timoffset 785 ); 786 ath_hal_intrset(ah, 0); 787 ath_hal_beacontimers(ah, &bs); 788 sc->sc_imask |= HAL_INT_BMISS; 789 ath_hal_intrset(ah, sc->sc_imask); 790 } else { 791 ath_hal_intrset(ah, 0); 792 if (nexttbtt == intval) 793 intval |= HAL_BEACON_RESET_TSF; 794 if (ic->ic_opmode == IEEE80211_M_IBSS) { 795 /* 796 * In IBSS mode enable the beacon timers but only 797 * enable SWBA interrupts if we need to manually 798 * prepare beacon frames. Otherwise we use a 799 * self-linked tx descriptor and let the hardware 800 * deal with things. 801 */ 802 intval |= HAL_BEACON_ENA; 803 if (!sc->sc_hasveol) 804 sc->sc_imask |= HAL_INT_SWBA; 805 if ((intval & HAL_BEACON_RESET_TSF) == 0) { 806 /* 807 * Pull nexttbtt forward to reflect 808 * the current TSF. 809 */ 810 tsf = ath_hal_gettsf64(ah); 811 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 812 do { 813 nexttbtt += intval; 814 } while (nexttbtt < tsftu); 815 } 816 ath_beaconq_config(sc); 817 } else if (ic->ic_opmode == IEEE80211_M_HOSTAP || 818 ic->ic_opmode == IEEE80211_M_MBSS) { 819 /* 820 * In AP/mesh mode we enable the beacon timers 821 * and SWBA interrupts to prepare beacon frames. 822 */ 823 intval |= HAL_BEACON_ENA; 824 sc->sc_imask |= HAL_INT_SWBA; /* beacon prepare */ 825 ath_beaconq_config(sc); 826 } 827 ath_hal_beaconinit(ah, nexttbtt, intval); 828 sc->sc_bmisscount = 0; 829 ath_hal_intrset(ah, sc->sc_imask); 830 /* 831 * When using a self-linked beacon descriptor in 832 * ibss mode load it once here. 833 */ 834 if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) 835 ath_beacon_start_adhoc(sc, vap); 836 } 837 sc->sc_syncbeacon = 0; 838 ieee80211_free_node(ni); 839#undef FUDGE 840#undef TSF_TO_TU 841} 842